Repository navigation
Bucket the Darling viewer's Overview CPU/wait/memory lanes server-side (#4234) - #4327
Merged
Merged
Conversation
The CPU tab and Overview CPU lane both read every ring-buffer sample with no cap (10,080 rows over a 7-day window, per the issue's own measurement). Buckets to TrendBudget.Chart's width, averaging each gauge with a NULL other-process value (SQL on Linux) coalesced to 0 before averaging so a bucket cannot drift from what the old per-row "NULL reads as 0" rule showed. A bucket holding exactly one physical sample is stamped at that sample's own raw time rather than the bucket grid, so a normal-width chart is unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TszxYhJJbTEh4LrZ56NYo3
GetTotalWaitTrendAsync and GetMemoryTrendAsync each read one row per collection with no cap (9,840 rows over a measured 7-day window). Buckets to TrendBudget.Chart's width: the wait lane is a rate (summed delta over summed interval, mirroring WaitTrendsSql's single-series case), the four memory metrics are gauges (averaged per bucket). A bucket holding exactly one physical collection is stamped at that collection's own raw time rather than the bucket grid, so a normal-width chart is unchanged; both live round-trip tests already exercise short windows that stay at 1-minute singleton buckets and pass unmodified. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TszxYhJJbTEh4LrZ56NYo3
…ew-trends-buckets # Conflicts: # PerformanceMonitor.Common/PerformanceMonitor.Common.csproj
ViewerCpuTempDbSqlTests still pinned the pre-bucketing CPU SQL shape (no AVG/GROUP BY, ORDER BY sample_time) against the now-bucketed CpuUtilizationSql; two tests failed. Updated them for the bucketed shape and added the ruling item 6 bucket-width source check the CPU read was missing (Overview's wait/memory reads already had theirs). TimeHonestyRungTests.BothWindowedCpuReads_... pinned the viewer's and MCP's CPU projections byte-identical at fixed column positions; #4234 nested the viewer's copy one indent level deeper inside a CTE, so the comparison now collapses whitespace runs instead, and the ORDER BY / $3 assertions split per reader since bucketing changed both (bucket ordinal instead of sample_time; $3 is now a bucket width, not absent). Ran ViewerCpuTempDbLivePostgresTests and ViewerOverviewLanesLivePostgresTests (T2b wrote these but never ran them against a rig) plus every class in the two files touched, DocCommentHygiene, ViewerTrendBucketingReviewTests, *OverviewLane*, *CpuTempDb* and TimeHonestyRungTests: all pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TszxYhJJbTEh4LrZ56NYo3
…ry (#4234) Ruling item 6 asks for two live pins per bucketed read that the base PR's tests didn't cover: a 7-day window returning at most TrendBudget.Chart's row budget (proves the cap actually bites, not just that the SQL text carries a width), and point equality with the old per-collection read when every bucket in a window holds exactly one physical collection, seeded off the minute grid (:37 seconds) so a fix that floors to the bucket grid line instead of the raw timestamp would fail it. Added both for all three reads (CPU, total-wait, memory), plus bulk generate_series seed helpers so the 7-day/10,080-row case doesn't pay a per-row round trip. Proved each of the 6 new tests fails on the old shape by temporarily forcing a fixed 1-minute bucket width (the budget tests) and forcing every point to the bucket_start instead of its raw timestamp (the singleton tests), confirming red, then reverting — no net source diff, test-only commit. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TszxYhJJbTEh4LrZ56NYo3
…ew-trends-buckets
erikdarlingdata
marked this pull request as ready for review
September 25, 2026 17:53
erikdarlingdata
enabled auto-merge (squash)
September 25, 2026 17:53
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.
Part of #4234.
Why
The Overview lanes' CPU, total-wait and memory reads each return one row per collection (or, for CPU, one row per ring-buffer sample) with no cap: 10,080 rows over 7 days for CPU, 9,840 for total-wait and memory, per the issue's own measurement. This buckets three of the five reads in T2b's brief to
TrendBudget.Chart's width, the same sizing contract PR #4304 (T1, merged as c51b43f) applied to the Wait Stats and Perfmon charts.What changes
Done, committed and pushed (T2b):
ViewerDataService.Cpu.cs(CpuUtilizationSql,GetCpuUtilizationAsync): bucketed. Both CPU columns are gauges (ruling item 2), averaged per bucket with no MAX/peak column (neither the CPU tab's own chart nor the Overview lane draws one).CpuUtilizationSample's two fields movedint->double. The read gained an optionalendUtcparameter (width sizing only); both real call sites now pass it.ViewerDataService.OverviewLanes.cs(TotalWaitTrendSql/GetTotalWaitTrendAsync,MemoryTrendSql/GetMemoryTrendAsync): bucketed. Wait is a rate (summed delta over summed interval, generalizingWaitTrendsSql's per-type case to one aggregate series,seriesCount=1). Memory's four MB metrics are gauges, averaged, no peak.Darling.Tests: updated the CPU and Overview-lanes SQL-text source checks and added bucket-width source checks (ruling item 6) for the Overview reads.BlockingTrendSql/DeadlockTrendSqlstay at their existing fixed one-minuteDATE_TRUNC— the MCP twin of this family stays fixed at one minute too, with no ladder or cap, and T3a's measurement put the real 7-day row counts at 297 and 41 (sparse, event-driven rows, not a dense per-collection series). Flagged for T2a/T3b's Lite lane to mirror "leave it."Done this pass (T2c — finishing the PR: ran the tests T2b wrote but never ran, fixed what broke, filled the gap):
ViewerCpuTempDbLivePostgresTestsandViewerOverviewLanesLivePostgresTestsagainst a real Postgres 18 + TimescaleDB rig for the first time. Both passed as committed, but two other test classes did not once actually exercised:ViewerCpuTempDbSqlTestsstill pinned the pre-bucketing CPU SQL shape (DoesNotContain("AVG(")/GROUP BY,ORDER BY sample_time) against the now-bucketedCpuUtilizationSql— 2 of 4 tests failed. The Overview file's equivalent SQL tests had been updated correctly; the CPU file's had not. Updated them for the bucketed shape and added the ruling item 6 bucket-width source check the CPU read was still missing.TimeHonestyRungTests.BothWindowedCpuReads_PreferTheStoredUtcInstant_AndKeepTheDeSkewAsTheFallbackpins the viewer's and the MCPget_cpu_utilization's CPU-read projections byte-identical at fixed column positions. WPF trend charts never adopted the #3897/#3960 bucket contract: at the "Last 7 days" window one chart reads 85–170 k raw rows, and the pickers re-run a week-long DISTINCT every refresh #4234 nested the viewer's copy one indent level deeper inside a newrawCTE, which shifted every line 4 columns over — genuinely breaking the literal pin (not a bug in the bucketing itself). Changed the comparison to collapse whitespace runs instead of comparing fixed columns, and split theORDER BY sample_time/$3assertions per reader, since bucketing changed both for the viewer only (bucket ordinal instead of the raw column;$3is now a bucket width, not absent).TrendBudget.Chart.AutoPointsrows (proves the cap actually bites: seeded at the real 1-per-minute cadence via a bulkgenerate_seriesinsert so 10,080 rows doesn't cost a per-row round trip), and point equality with the old per-collection read when every bucket in a window holds exactly one physical collection, seeded off the minute grid (:37seconds) so a fix that floors to the bucket grid line instead of the raw timestamp would fail it. Proved each of the 6 fails on the old shape: temporarily forced a fixed 1-minute bucket width for the budget tests, and forced every point to stamp atbucket_startinstead of its raw timestamp for the singleton tests; both variants turned every corresponding test red, then were reverted (no net source diff from this proof).PerformanceMonitor.Common.csprojmerge conflict againstorigin/dev(which landed the sameInternalsVisibleToforPerformanceMonitor.Darling.Viewervia WPF Wait Stats and Perfmon trend charts bucket server-side (#4234) #4304/T1, as this PR's own description predicted): kept one copy, combined the two comments so it names both the Wait Stats/Perfmon charts (already ondev) and this PR's Overview lanes/CPU chart.origin/devtwice (once at the start of this pass, once again after adding the new tests, since dev moved again in between) — both merges clean except the onecsprojconflict above; rebuilt and re-ran the full required class set after each.Not done: Performance Trends moved to lane T2d's PR.
Test plan
Darling/Darling.Tests/Darling.Tests.csprojbuilds with 0 Warning(s), 0 Error(s) after every commit (5 rebuilds this pass).DARLING_TEST_PGset, migrations applied) — run for the first time this pass.ViewerCpuTempDbSqlTests: 12 passed (2 fixed, 1 added, rest unchanged).ViewerCpuTempDbLivePostgresTests: 6 passed (4 existing + 2 new).ViewerOverviewLanesSqlTests: 9 passed (unchanged from T2b).ViewerOverviewLanesLivePostgresTests: 7 passed (3 existing + 4 new).ViewerTrendBucketWidthSqlTests: 3 passed.ViewerNameListCacheTests: 5 passed.ViewerTrendBucketingLiveTests: 6 passed.TimeHonestyRungTests: 8 passed (1 fixed).TimeHonestyRungLivePostgresTests: 1 passed.DocCommentHygieneTests: 77 passed.git merge origin/dev, twice; clean except the one documentedcsprojconflict; rebuilt and re-ran the class set above after each.What the coordinator should double-check
origin/devcleanly as of this pass (merge commits included); the one real conflict (thePerformanceMonitor.Common.csprojInternalsVisibleTocomment, from WPF Wait Stats and Perfmon trend charts bucket server-side (#4234) #4304 landing the same entry) is resolved by keeping one copy with a combined comment.CHANGELOG entry
SECTION: Changed
ENTRY:
REF:
[Bucket the Darling viewer's Overview CPU/wait/memory lanes server-side (#4234) #4327]: Bucket the Darling viewer's Overview CPU/wait/memory lanes server-side (#4234) #4327
🤖 Generated with Claude Code
https://claude.ai/code/session_01FVjn4PBJN71NQXdFo6ZxNQ