You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Split out of #2545 so it is tracked as its own work rather than sitting in a comment. This is the shared foundation every extension-backed collector would need, and it is useful on its own.
The distinction
We have two capability axes, both derived from the collectors' own AppliesTo gates:
Both answer "this collector can never run here", and both are properties of the target, fixed for the life of a connection. That is what makes the sweep-and-derive machinery (#2518) sound: every fact a gate reads is a scalar, and the derivation walks a finite cross-product of them.
A missing extension is a different kind of fact, and it does not belong on that axis:
It is mutable at runtime. Engine kind, edition and version cannot change under a live connection. Someone can CREATE EXTENSION pg_stat_kcache while the service is running. A collector gated off at connect time would stay off until a reconnect — silently, and with no way for the operator to tell why installing the extension we recommended changed nothing.
It is set-valued.CollectorTargetInfo carries nine facts today, all bool or int, none set-valued. "Which of these N extensions are installed" is a set, which is 2^N combinations if swept naively. (There is a way out — the IL decoder in CollectorEngineCapabilityDerivationTests already knows which facts each gate reads, so only extensions something genuinely gates on need sweeping — but it is still surgery on the sweep model, and point 1 makes it the wrong surgery.)
The answer is actionable, and the others are not. "Your engine cannot do this" is final. "pg_stat_kcache is not installed — add it to shared_preload_libraries and it will start collecting" is a setup step. Those deserve different words.
What to build
A third miss shape alongside empty / not_collected / unavailable, evaluated at read time rather than at gate time: the read attempts, finds the surface absent, and answers naming the precondition and how to satisfy it.
Because it is re-evaluated per read, an extension installed five minutes ago is picked up on the next cycle — which is exactly what someone following our own advice expects to happen, and is the property an AppliesTo gate could not give.
Why it is worth having independently of extensions
The same shape covers preconditions we already handle inconsistently:
Query Store not enabled on a monitored database — a setup step, currently indistinguishable from "no data".
HasMsdbAccess — already an AppliesTo fact, and arguably in the wrong place for the same reason: it describes a grant, which someone can change without a restart.
That last one is worth checking early. If msdb access belongs in this vocabulary rather than on the capability axis, this issue is not new machinery for PostgreSQL — it is the right home for something SQL Server already gets slightly wrong.
#2545 (extension-aware PostgreSQL collection) is the umbrella and a stated stretch goal. This is the piece worth doing first and independently: no sweep changes, no IL-guard changes, and it makes each extension-backed collector a self-contained addition afterwards.
Split out of #2545 so it is tracked as its own work rather than sitting in a comment. This is the shared foundation every extension-backed collector would need, and it is useful on its own.
The distinction
We have two capability axes, both derived from the collectors' own
AppliesTogates:system_health, permanently.Both answer "this collector can never run here", and both are properties of the target, fixed for the life of a connection. That is what makes the sweep-and-derive machinery (#2518) sound: every fact a gate reads is a scalar, and the derivation walks a finite cross-product of them.
A missing extension is a different kind of fact, and it does not belong on that axis:
CREATE EXTENSION pg_stat_kcachewhile the service is running. A collector gated off at connect time would stay off until a reconnect — silently, and with no way for the operator to tell why installing the extension we recommended changed nothing.CollectorTargetInfocarries nine facts today, allboolorint, none set-valued. "Which of these N extensions are installed" is a set, which is 2^N combinations if swept naively. (There is a way out — the IL decoder inCollectorEngineCapabilityDerivationTestsalready knows which facts each gate reads, so only extensions something genuinely gates on need sweeping — but it is still surgery on the sweep model, and point 1 makes it the wrong surgery.)pg_stat_kcacheis not installed — add it toshared_preload_librariesand it will start collecting" is a setup step. Those deserve different words.What to build
A third miss shape alongside
empty/not_collected/unavailable, evaluated at read time rather than at gate time: the read attempts, finds the surface absent, and answers naming the precondition and how to satisfy it.Because it is re-evaluated per read, an extension installed five minutes ago is picked up on the next cycle — which is exactly what someone following our own advice expects to happen, and is the property an
AppliesTogate could not give.Why it is worth having independently of extensions
The same shape covers preconditions we already handle inconsistently:
system_healthXE session stopped on a SQL Server that supports it — genuinely fixable, and today it lands in the sameunavailablebucket as engines that can never have it, which On Azure SQL DB, twelve reads tell you to go start a capture that cannot exist there #2511 deliberately separated at the engine level but not at the session level.HasMsdbAccess— already anAppliesTofact, and arguably in the wrong place for the same reason: it describes a grant, which someone can change without a restart.That last one is worth checking early. If msdb access belongs in this vocabulary rather than on the capability axis, this issue is not new machinery for PostgreSQL — it is the right home for something SQL Server already gets slightly wrong.
Relationship to #2545
#2545 (extension-aware PostgreSQL collection) is the umbrella and a stated stretch goal. This is the piece worth doing first and independently: no sweep changes, no IL-guard changes, and it makes each extension-backed collector a self-contained addition afterwards.