Skip to content

LITE: the Collection Log drill window says where its data starts (#4966) - #5031

Merged
erikdarlingdata merged 1 commit into
devfrom
feature/4966-lite-drill
Oct 3, 2026
Merged

erikdarlingdata merged 1 commit into
devfrom
feature/4966-lite-drill

Conversation

@erikdarlingdata

@erikdarlingdata erikdarlingdata commented Oct 3, 2026 •

Copy link
Copy Markdown
Owner

Part of #4966.

The Collection Log grid on a server's tab already says where its data starts when the range reaches before it. The per-collector run-history window (opened from a Collection Health row) read a week of one collector's runs and said nothing. It now says it, the way the Darling viewer's drill window already does (#5010).

What changes

  • The window shows a "Showing since " note under its summary when the server's collection log starts after the 7 days the window reads. It is the same amber band, the same words and the same 90-minute slack as the Collection Log grid's note. A quiet start (the log reaches back to the week's start, or the first run lands within the slack) shows nothing.
  • Coverage rule, over the SERVER's log. The note comes from the Collection Log probe (GetQueryWindowFloorAsync with QueryWindowRelation.CollectionLog), never from the collector's own first run. A collector that started late in a week the server's log covers says nothing. The read has no row cap, so the capped grids' oldest-row rule does not apply, and the window uses the shared guard (ServerTab.ProbeWindowFloorOrNullAsync) and banner rule (ServerTab.ApplyWindowFloorToBanner) as they are, with no copy.
  • The week is worked out once. CollectionLogWindow.ReadDrillAsync takes one end (now, or a pinned instant for tests), puts the start 168 hours before it, and hands that same pair to the read and to the probe. GetCollectionLogByCollectorAsync now takes (startUtc, endUtc) instead of hoursBack, so the read can no longer read a clock of its own. It is bounded on both ends, both inclusive, as the probe is, which means a run stamped after the moment the window opened is no longer listed.
  • A failed probe shows no note and costs no rows. The probe runs through the guard the tab uses: a throw is logged at warning, the answer is null, the note stays hidden (a stale one is cleared) and the rows load as before.
  • The note names its time in the zone the window's grid prints its times in. The grid words each run through CollectionHealthTime.Format. That choice (the display mode's zone for the window's server clock, else the active tab's) now lives in one CollectionHealthTime.Zone, which Format and the note both call: Server time uses the window's server clock, Local time this machine's zone, UTC is UTC.
  • The load is split into a read (ReadDrillAsync, no controls touched) and a note step (ShowDrillDataStart, run on the UI thread after the rows are bound), so a test can drive the read and the note without opening the window. The read itself still starts on the UI thread's context, as it did before this PR.

Files: Lite/Windows/CollectionLogWindow.xaml and .xaml.cs, Lite/Services/LocalDataService.CollectionHealth.cs, and the new Lite.Tests/CollectionLogDrillDataStartTests.cs.

Test plan

New class CollectionLogDrillDataStartTests (10 tests: a real DuckDB store for the coverage cases, passed-in steps for the probe that throws and the recorded window). Nothing in it depends on today's date: the window's end is pinned.

RED first. The window as shipped has no seam to call, so the new tests do not compile against it. To see each one fail by assertion I put the old behavior behind the new members and ran the class twice:

  • Stub A, the old behavior: the read takes the week from its own clock, no probe, no note. 9 of 10 failed. For example TheReadAndTheProbe_AreGivenTheSameWindow: expected the window (2026-09-13 12:00Z, 2026-09-20 12:00Z), actual (2026-09-26 16:38Z, 2026-10-03 16:38Z), the read's own clock.
  • Stub B, the right window handed to the read, but still no probe and no note. 8 of 10 failed:
    • ACollectorThatStartedLateInACoveredWeek_ShowsNoNote RED: expected floor 2026-09-13T12:00Z (the server's log covers the week), actual null. A no-note case can only go red through what it asks of the probe: nothing asks.
    • AServerWhoseFirstCollectionFallsInsideTheWeek_NamesIt RED: expected floor 2026-09-15T09:30Z, actual null.
    • TheReadAndTheProbe_AreGivenTheSameWindow RED: Assert.Single on the probe's recorded windows, which is empty.
    • AProbeThatThrows_ShowsNoNote_AndTheRowsStillLoad RED: expected 1 probe call, actual 0.
    • TheNote_IsWordedInTheZoneTheGridPrintsItsTimesIn RED: expected floor 2026-09-15T13:30Z, actual null.
    • TheRows_AreTheCollectorsRunsInsideTheWindow_BothEndsInclusive RED: expected floor 2026-09-13T12:00Z, actual null (under stub A the same test failed on its row count: expected 15, actual 0).
    • AFirstCollectionJustInsideTheSlack_ShowsNoNote RED: expected floor 2026-09-13T12:45Z, actual null.
    • TheWindow_LoadsAndWordsItsNoteThroughTheSharedSteps (source scan of the window's wiring and its banner) RED: expected one ShowDrillDataStart(CollectionLogDrillTruncatedBanner ... call, found 0.
  • Two tests did not go red under stub B, and why: TheReadTakesTheWindow_NotAnHoursBack (a reflection pin that the read has one overload, taking startUtc and endUtc; the stub already carried the data-service change, and against the shipped file it fails by construction because that overload takes hoursBack, which I did not run), and AWeekWithNoRunAtAll_ShowsNoNote_AndNoRows (a guard that a week with nothing in it shows no note; no window that never shows a note can fail it).

GREEN with the real change:

  • CollectionLogDrillDataStartTests: Total 10, Failed 0.
  • Targeted Lite classes, one run: DataStartBanner*, QueryWindowTruncationTests, DisplayZoneTextFrameTests, DisplayZone*, ServerTimeHelper*, CollectionLog*, CollectionHealth*, GridTimeColumnSortMemberTests, and every class that names CollectionLogWindow, GetCollectionLogByCollectorAsync or CollectionHealthTime (CollectionOutputBesideCostTests, CollectorHealthClassifierTests, DuckDbSentinelConnectionTests, EmptyEnumerationNoteTests, EngineGapNoteTests, LastErrorCurrencyTests, RegressedFromProductiveTests, SwallowedItemFailureTests): Total 551, Failed 0.
  • RepoFileAdoptionTests, DocCommentHygieneTests, CommentFilterAdoptionTests (Darling.Tests): Total 83, Failed 0.
  • Lite.Tests and Darling.Tests build with 0 Warning(s), 0 Error(s).
  • The full suite (not part of this job).
  • Not looked at on screen: the app was not started, so the banner's placement under the summary line is unchecked by eye. The XAML compiles and the banner is declared collapsed in the tab's amber.

Notes

  • Zone. The note uses CollectionHealthTime.Zone(_serverClock): the window's server clock in Server time, else the active tab's clock, this machine's zone in Local time, UTC in UTC. That is exactly the zone the window's rows print theirs in, and the one the server tab's picker uses for the Collection Log grid's own note, since the window is opened from that tab with that tab's clock.
  • Removed overload. GetCollectionLogByCollectorAsync(serverId, collectorName, hoursBack = 168) is gone. The window was its only caller (searched the whole repository), and an overload that reads its own clock is the way the read and the probe came apart. The reflection pin keeps it that way.
  • Read, then probe, not side by side. The Darling viewer's drill starts its probe beside its read. Lite's tab awaits the probe after its reads, and the drill's two queries are small, so this does the same.
  • Left: nothing from the brief. Lite's Duration Trends label and hover clear went into Lite: Collection Log, System Events, Config Changes and Long Queries say where the data starts, and Duration Trends draws the whole range (#4966, group C) #4989.

CHANGELOG

No entry in this PR. The release owner adds it under [Unreleased].

Proposed entry:

SECTION: Fixed
ENTRY:
- **Lite's per-collector Collection History window now says where its data starts** ([#5031]) - The window lists one collector's runs over the last 7 days and said nothing when the server's collection log started after that week began, so a short list looked complete. It now shows a "Showing since" note, worded from the server's collection log (a collector that started late in a week the server's log covers says nothing) and in the same time zone the window's run times use. The note is hidden when the log reaches back to the week's start (to within 90 minutes), and a failed lookup hides the note without costing the list any rows. The list also now stops at the moment the window opened, which is where the note's lookup stops.
REF:
[#5031]: https://github.com/erikdarlingdata/PerformanceMonitor/pull/5031

The per-collector run-history window listed a week of one collector's runs and said nothing when the server's collection log started after that week began. It now shows the same "Showing since" note as the Collection Log grid, worded from the SERVER's log through the shared probe guard and banner rule, in the zone the window's rows print their times in.

The week is worked out once and handed to both the read and the probe: GetCollectionLogByCollectorAsync takes (startUtc, endUtc) instead of hoursBack and is bounded on both ends like the probe. A probe that throws shows no note and the rows still load.
@erikdarlingdata
erikdarlingdata marked this pull request as ready for review October 3, 2026 17:27
@erikdarlingdata
erikdarlingdata merged commit cbeab6c into dev Oct 3, 2026
22 of 24 checks passed
@erikdarlingdata
erikdarlingdata deleted the feature/4966-lite-drill branch October 3, 2026 17:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant