Lite gets the Query Store backfill off switch (#2167 parity) - #2176
Conversation
Completes what #2168 shipped for Darling. Lite reads App. QueryStoreBackfillEnabled live in the due-check, so the Settings checkbox takes effect without a restart — matching Darling's store-reload behavior rather than requiring an app bounce. Two details worth the lines they cost: the switch is checked BEFORE the due-time stamp, so a disabled backfill does not consume its own schedule and re-enabling runs on the next due tick instead of waiting out an interval that elapsed while it was off; and the log records each TRANSITION once rather than once per idle tick, seeded true so a deployment that never touches the switch logs nothing about it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| <CheckBox x:Name="AnalysisEnabledCheckBox" Content="Enable automated analysis" | ||
| Margin="20,4,0,0" Foreground="{DynamicResource ForegroundBrush}"/> | ||
| <CheckBox x:Name="QueryStoreBackfillCheckBox" Content="Fill Query Store history gaps in the background" |
There was a problem hiding this comment.
Nit: this checkbox (and its description) is grouped under "Automated Analysis" ("Periodically run the triage engine and record findings in the Alerts tab..."), but Query Store backfill has nothing to do with the analysis/triage engine — it's a data-collection concern. On the Darling side this same control sits next to "Capture execution plans" in the collection-related group (Darling/PerformanceMonitor.Darling.Viewer/SettingsWindow.xaml:85), which is the more discoverable placement. Consider moving this checkbox (and the matching App.xaml.cs:180 field, which is likewise sandwiched between AnalysisEnabled and AnalysisNotificationsEnabled) out of the analysis grouping so it doesn't read as an analysis-engine toggle.
ReviewWent through the diff against the Darling implementation from #2168 for parity, and traced the due-check/switch/log logic in Correctness / parity: This holds up. The core logic is sound:
No SQL in this diff (pure C#/XAML), no injection/secrets/network surface touched, and no missing-index-DMV territory to worry about. One nit posted inline: the new checkbox and its backing field are grouped under "Automated Analysis" in both the XAML and Didn't find anything else worth flagging — this is a small, self-contained parity fix and it reads like one. |
I modeled the wiring on AnalysisEnabled and inherited its SECTION along with its pattern, so a data-collection control landed under Automated Analysis — where nobody looking for it would think to look, and where it reads as an analysis-engine toggle. The App field was sandwiched between the two analysis flags for the same reason. Now beside Pause Collection, the other 'should collection do this' affordance, which is also where Darling puts its equivalent (next to plan capture in the collection group). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Taken — and the diagnosis of how it happened is exactly right. I modeled the wiring on Moved to the Collection Control section, beside Pause Collection — the other "should collection do this" affordance — which is also where Darling puts its equivalent, next to plan capture. Field re-homed out of the analysis block too, with a comment recording why, so a future copy-the-pattern edit doesn't drift it back. |
| more than the history is worth; live collection is unaffected and re-enabling resumes exactly | ||
| where the watermarks left off, so nothing is lost by pausing it. Darling's equivalent is a store | ||
| column (V58) because a headless service has no window to click. */ | ||
| public static bool QueryStoreBackfillEnabled { get; set; } = true; |
There was a problem hiding this comment.
Minor organizational nit: this property (and its doc comment) landed directly under the /* System tray settings */ header, ahead of MinimizeToTray — the actual first tray setting. QueryStoreBackfillEnabled isn't a tray setting, so as written it reads as grouped under that section.
This is the same class of mistake the PR's second commit deliberately fixed for the checkbox's XAML placement ("Put the backfill checkbox where it belongs (review catch)") — worth moving this property above the /* System tray settings */ comment (or giving it its own section comment) so the C# side gets the same care the XAML side got.
|
Reviewed the diff (App.xaml.cs, CollectionBackgroundService.cs, SettingsWindow.xaml/.xaml.cs, CHANGELOG.md). Summary: Solid parity implementation. Compared against Darling's V58 backfill switch (
One nit (posted inline on No correctness, security, or Lite/Darling parity issues found otherwise. |
Second instance of the same mistake in one PR: I moved the field out of the analysis block and dropped it under /* System tray settings */, ahead of the actual first tray setting. Fixing the XAML placement and then reproducing the error in C# is exactly the drift the earlier commit message claimed to be preventing. Now under its own /* Collection settings */ header, with the tray header restored to the tray setting it belongs to. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Fair hit, and worse than a nit given the context: I fixed the XAML placement, wrote a commit message about not letting copy-the-pattern drift the grouping, and then landed the C# field under Now under its own |
Unrelated to this PR's feature, but it BLOCKED this PR, so it lands here: two AnomalyDetectorTests fail deterministically for CI runs between 03:39 and 04:00 UTC. My push at 03:55 hit it. The seed helpers write ~21 minutes of samples starting at whatever time-of-day _analysisStart inherited from DateTime.UtcNow. When that start lands within 21 minutes of midnight the span crosses a date boundary, so each intended 'day' contributes TWO distinct dates — 4 instead of 2 — which clears the Full tier's 3-distinct-day minimum, makes a deliberately-thin baseline trustworthy, and routes the detector down the z-path. baseline_low_quality then reads 0 where the test requires 1. Floored to the hour rather than midday-anchored (#1972's discipline elsewhere) because the Full tier buckets by hour AND day-of-week: the seeds must keep _analysisStart's hour and weekday to land in the bucket the analysis window reads. Starting at :00 keeps both and makes a 21-minute span unable to leave the hour. Applied to all seven seed helpers, not just the two that failed — they all share the shape. A rerun after 04:00 would have passed and hidden this. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Round-3 build failed, and it was NOT this PR — but it blocked it, so the fix rides along in Two Fixed by flooring the seed start to the hour. Deliberately NOT midday-anchoring (the #1972 discipline used elsewhere in the suite) because the Full tier buckets by hour AND day-of-week — the seeds have to keep Worth noting: a rerun after 04:00 UTC would have passed and hidden this permanently. |
|
Reviewed. This is a clean, well-scoped port of the #2167 backfill off-switch to Lite, and it holds up well against Darling for parity: Parity check — good:
One thing worth a mention: No correctness, security, or performance issues found in the core change. |
What
Completes #2167. Darling got the switch as a store column in #2168 (V58); Lite now gets it as a Settings checkbox — "Fill Query Store history gaps in the background", default on, persisted to
settings.jsonasquery_store_backfill_enabled.Two details that aren't obvious
The switch is checked BEFORE the due-time stamp. If it were checked after, a disabled backfill would still consume its own schedule, and flipping it back on would wait out an interval that elapsed while it was off. Checked first, re-enabling runs on the next due tick.
Read live, not captured. The due-check reads
App.QueryStoreBackfillEnabledeach pass, so the checkbox takes effect without restarting Lite — the same responsiveness Darling gets from its store reload. A captured bool would have quietly required an app bounce, which is the kind of thing nobody notices until they're mid-incident wondering why the switch did nothing.Transition-logged once, not once per idle tick, seeded
trueto match the default so a deployment that never touches the switch says nothing about it in the log.Why the two apps differ in surface
Darling's is a store column because a headless service has no window to click, and its operator may be nowhere near the box. Lite's is a checkbox because it has a settings window and a single local user. Same behavior, appropriate surface each — noted in both places so the asymmetry reads as deliberate.
Testing
Lite builds clean. The behavior is a two-branch gate on a settings bool in a background loop; there's no seam to unit-test that wouldn't just be asserting
if (!flag) return;back to itself. The Darling half's store/probe/gate plumbing is pinned inBackfillSwitchTestsfrom #2168.Closes #2167 (its Darling half shipped in #2168).