fix(cnpg): observe the per-statement export instead of its manifests #392
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/query-stats-runtime-guard"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What I found
While adding per-statement measurement for the Binjovi performance work, I found the
pg_stat_statementsexport has been producing nothing since 2026-09-04, and every existing check passed the whole time.shared_preload_librariespg_stat_statementspostgres-query-statsConfigMapDatabase/monitoringspec.extensionspg_stat_statements,ensure: presentDatabase/monitoringstatusapplied: true,extensions[0].applied: trueSELECT extversion FROM pg_extensioninmonitoringcnpg_pg_stat_statements*series in VictoriaMetricsEvery file in every database carries a creation time of 2026-09-04 12:49:52 and
pg_stat_checkpointer.stats_resetis 2026-09-04 12:50:12, so the data plane was re-initialised that day. The Database object was not recreated with it: created 2026-08-07, stillgeneration: 1.That is documented CloudNativePG behaviour, not a bug. From the Database CRD documentation: "Once reconciled, a
Databaseobject will not be reapplied unless itsmetadata.generationchanges, giving flexibility for direct PostgreSQL modifications." An initdb behind a surviving object is exactly that case, so the operator never looks again and the staleapplied: trueoutlives the database it describes.tests/cnpg-custom-queries.shcould not have caught this. That guard checks the delivery chain in the repository and every link was intact. Nothing in the repository was wrong. Only the running database disagreed.Change
Repair, in
cnpg-instance/query-stats.yaml. Declareschema: publicon the extension. It says where the objects go instead of leaving it to the control file, and editing the spec increments the generation, which is the only supported way to make the operator apply the extension again.kubectl apply --dry-run=serverreports the object asconfigured, so the generation does move.This repairs today and nothing more. The next re-initialisation loses the extension again and reports success again.
make rebuildis routine here, so a one-time repair is not a fix.The durable half, in
alerting/rules.yaml.PostgresQueryStatsAbsentwatchescnpg_pg_stat_statements_info_tracked, the exact series thepg_stat_statements_infoblock emits, and fires after an hour of absence. It follows theCnpgBackupMetricMissingpattern already in that file. One hour rather than five minutes because only the primary exports, so a failover or a rolling restart is a normal gap.Expect it to fire on merge and go quiet once the extension is back. That is the alert telling the truth about the current state.
The guard, in
tests/cnpg-custom-queries.sh. The manifest chain checks stay as they are. A new section requires the alert to exist and to name a series the ConfigMap actually produces, because a rule on a misspelled series is the same silence with extra YAML.Tests
tests/cnpg-custom-queries.shpasses, including its existing damage cases. Three new damage cases against the runtime guard are each rejected: dropping the alert, misspelling the series, and changing the expression so it no longer tests absence.kubectl apply --dry-run=serveraccepts both files.Not done here
The
binjovidatabase still has no per-statement visibility of its own. That was the original goal, and it is a separate decision:pg_stat_statementsis one cluster-wide hash table, so the deliberate design is to read it from the singlemonitoringdatabase rather than install it per tenant. Once this export is alive again, Binjovi statements are already visible there through thedatnamelabel.https://claude.ai/code/session_015dkyh6itUFos3aSZnomh2w