Repository navigation
Top-N reads answer empty, not unavailable, when the collector ran and stored nothing (#6226) - #6232
Merged
Merged
Conversation
erikdarlingdata
marked this pull request as ready for review
October 20, 2026 15:27
erikdarlingdata
enabled auto-merge (squash)
October 20, 2026 15:27
This was referenced Oct 20, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Claude posting for Erik Darling.
Closes #6226.
Why
get_top_queries_by_cpuansweredunavailable("No query stats available for the specified time range.") for a window in whichquery_statsran successfully every minute and stored 0 rows, because nothing executed since its watermark. By the status words the server defines, that isempty(we looked, and nothing ran);unavailablemeans "could have it, does not right now: check collection health". #6127 already fixed the case where snapshots were stored without deltas. This is the remaining case: the collector ran and found nothing.What changes
One shared sentence,
CollectorRunFacts.RanFoundNothing(PerformanceMonitor.Common), used by both products. It returns null unless the collector has a successful (status SUCCESS) run inside the window. The ranking's empty path now ends:not_collected(unchanged, still first), then the #6127 snapshot answer (unchanged), then, new,emptywhen the run count is above zero, thenunavailableas before.Answer for a window with runs:
{"status":"empty","message":"query_stats ran 6 time(s) in the last 1 hour(s) and found no executed statements to store. This is not a collection gap: ...","hints":{"successful_runs_in_window":6}}. With a database filter the sentence claims only that database ("stored no executed statements for database 'X'"), since the runs may have stored rows for other databases.Tools, Darling and Lite matching where the tool exists in both:
get_top_queries_by_cpu(Darling and Lite). Darling applies it on the raw tier only, as get_top_queries_by_cpu answers unavailable for a window in which query_stats stored rows #6127 does: a window the hourly rollup serves has its own rows and a run count says nothing about it.get_query_store_top(Darling and Lite). Collectorquery_store; sits after the existing Query Store precondition and first-interval answers, before the finalunavailable. Darling applies it only when the raw tier answered (no interval table or daily summary served) and the window is within the raw retention span, becausecollection_logoutlives the raw rows and a longer window's runs prove nothing about the dropped part. Lite has no rollup tier, so no such guard.get_pg_top_queries(Darling only; Lite has no PostgreSQL reads). Collectorpg_statement_stats. It also needs two successful runs overall (the existing delta-baseline rule): the first run stores nothing by design, so one run is not yet a measurement. Same retention-span guard.get_top_procedures_by_cpu(both). [BUG] MCP tool audit on 3.9.0-nightly.20261006.515: 23 defects (blocking, spills, FinOps, store, tool payloads) #5633 answersemptyfrom the procedure_stats run history; this reuses its data path.Test plan
New behaviour tests, Darling live (
TopReadsCollectorRanEmptyLiveTests, 6 tests) and Lite (McpTopReadsCollectorRanEmptyTests, 5 tests): a window with successful zero-row runs givesemptywith the count; a window with only a failed run and an older successful run staysunavailable; the get_top_queries_by_cpu answers unavailable for a window in which query_stats stored rows #6127 snapshot answer is unchanged even when the collector ran; a database filter names only that database;get_query_store_topempty/unavailable, plus the retention-span guard (Darling);get_pg_top_queriesstaysunavailableon one run and goesemptyon two.Reverted the three source files to dev and re-ran the new classes: Darling 3 of 5 failed (the three empty cases), Lite 3 of 5 failed. The unchanged-behaviour cases passed on both.
Darling live run on a throwaway PostgreSQL store:
TopReadsCollectorRanEmpty*+TopQueriesSnapshotOnlyWindow*: 8 of 8 pass. Then 1857 tests (Census, Ratchet, QueryStore, TopQueries, McpPageContract, the PG top-queries and statement classes, CollectorRunEmptyReason): 0 failed, 2 skipped.Lite: Mcp, QueryStore, TopQueries, TopProcedures, CollectorRun, Census and Ratchet classes: 1245 run, 0 failed.
Both test projects build with 0 warnings from my change (Darling.Tests: 0 Warning(s)).
bash .github/scripts/pre-push.shfrom PowerShell 7: Guard stages green (Darling 4446 run, 0 failed; Lite 1196 run, 0 failed). Its last line (one word of the gate's own wording changed):GATE STOP: selection is the whole suite (darling 2030, lite 600): run the touched classes; CI decides (over PRE_PUSH_MAX_CLASSES=400 in one project; no selected class ran; logs /tmp/pre-push.P6t3Nn)The gate cannot select fewer than 400 classes here, so the classes listed above are the ones I ran; CI decides the rest.
Not run: the full Darling and Lite suites; Installer.Tests.
Proposed CHANGELOG line
SECTION: Fixed
get_top_queries_by_cpu,get_query_store_topandget_pg_top_queriesansweredunavailable(check collection health) for a window in which the collector ran successfully and stored no rows because nothing executed. They now answeremptywithsuccessful_runs_in_window, and keepunavailablefor a window with no successful run. Darling and Lite match; the Darling reads apply it only where the raw tier holds the whole window.For the maintainer to double-check
get_top_queries_by_cpustill ends inunavailableon an empty page, by design (see above).