Lite: Blocking Stats severity sub-tab (Tier-1 parity)#1514
Merged
Conversation
Port Darling's Blocking Stats sub-tab to Lite: a 2x2 chart grid + summary strip showing blocking AND deadlock SEVERITY over the window (the "getting WORSE, not just more frequent" signal), the severity companion to Lite's existing count-only Blocking Trends sub-tab. Appended as the LAST Blocking sub-tab (sub-index 4, after Deadlocks) so nothing reindexes; RefreshBlocking Async's subTabOnly switch gains case 4 and the full-refresh path renders it. Blocking stays top-level index 8. Reader (LocalDataService.BlockingStats.cs) adapts Darling's aggregates to DuckDB: block-duration SUM/MAX/AVG(wait_time_ms) per minute over the same XE-preferred + DMV-fallback (WHERE NOT EXISTS) union the count trend uses (honoring the #1319 DB filter on both arms), and a deadlock-severity aggregate over deadlock_graph_xml on the same v_deadlocks/collection_time window as the count (uncapped), parsed off-thread with Lite's own DeadlockProcessDetail .ParseFromRows and bucketed by minute (victim_count + total/max/avg wait). Collapse check: Darling's deadlock-severity computation is NOT a viewer<-> service twin -- the service/MCP side hosts only count trends and deliberately omits a blocking_deadlock_stats aggregate, and the Darling viewer already parses via shared Common.DeadlockGraphParser -- so per the brief Lite reuses its own existing ParseFromRows (internally consistent with its Deadlocks grid) rather than adding a third copy. Nothing on the Darling side touched. Four charts (ServerTab.BlockingStats.cs) mirror Darling with Lite's chart idioms (ChartStyle/ChartHoverHelper, SeriesColors/ChartPalette, UtcOffset Minutes axis, Y-floor-at-0, window-padded scatter), wired into the Blocking TabControl + ServerTab.xaml.cs init/dispose. Real-DuckDB round-trip tests (BlockingStatsReaderTests) assert the duration aggregate, the XE->DMV fallback, the #1319 filter, window bounding, and the deadlock-severity aggregate reconciling with the deadlock count. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
What
Ports Darling's Blocking Stats sub-tab to Lite: a 2×2 chart grid + a window summary strip showing blocking and deadlock SEVERITY over the window — the "are blocks/deadlocks getting worse, not just more frequent" signal. It is the severity companion to Lite's existing Blocking Trends sub-tab (which plots COUNTS).
Everything is computed on-the-fly from rows the store already keeps — no collector, no migration — the Lite equivalent of the Dashboard's pre-aggregated
collect.blocking_deadlock_stats.Sub-tab wiring (append-at-end, zero reindex)
<TabItem Header="Blocking Stats">appended as the LAST Blocking sub-tab → sub-index 4 (after0 Trends, 1 Current Waits, 2 Blocked Process Reports, 3 Deadlocks). Current Waits / BPR / Deadlocks are untouched; the DrillDown/DailySummary navigations that target sub-indexes 2 and 3 are unaffected.RefreshBlockingAsyncgainscase 4in thesubTabOnlyswitch (loads on sub-tab switch + timer tick when visible) and the two reads in the full-refresh path (first-load / manual refresh), matching how Trends/Current Waits are in both.RefreshVisibleTabAsyncuntouched.ServerTab.xaml.csalongside the other chart-tab partials.Collapse check — NOT twinned (viewer-only aggregate; parse already shared)
Darling's deadlock-severity computation is not a viewer↔service twin:
DarlingBlockingTrendReader/DarlingMcpBlockingTools) hosts only the count trends and explicitly documents thatget_blocking_deadlock_stats/ the victim-wait severity is not hosted (no raw source).AggregateDeadlockSeverity) is viewer-only and already parses via the sharedPerformanceMonitor.Common.DeadlockGraphParser.So there is no twin to collapse. Per the brief's not-twinned branch, Lite reuses its own existing
DeadlockProcessDetail.ParseFromRows(the same parse the Deadlocks grid uses, keeping Lite's severity internally consistent with its grid) rather than introducing a third copy of the parse. Nothing on the Darling side was touched.Reads (
Lite/Services/LocalDataService.BlockingStats.cs)GetBlockingDurationStatsAsync— per-minuteCOUNT(*)+SUM/MAX/AVG(wait_time_ms)over the same XE-preferred (v_blocked_process_reports) + DMV-fallback (v_dmv_blocking_snapshots,WHERE NOT EXISTS) union the blocking-incident count trend uses, so the severity chart and count chart never disagree on which rows exist. Honors the [FEATURE] Add filter for databases(s) #1319 database filter on both arms.GetDeadlockSeverityStatsAsync— reads rawdeadlock_graph_xmlover the samev_deadlocks/collection_timewindow as the deadlock count (uncapped, so it can't drop rows the count keeps), parses each graph off the UI thread withParseFromRows, and buckets the per-process victim/wait rows by minute (victim_count= SUM of victims; total/max/avg over every process's wait).Charts + summary (
Lite/Controls/ServerTab.BlockingStats.cs)Four charts (block Max/Avg + block Total; deadlock Max/Avg + deadlock Total — Total split onto its own axis per pair so the aggregate magnitude doesn't swamp the per-incident one) + a summary strip (events / total / max / avg block duration, deadlock count, deadlock victims, deadlock wait). Mirrors Darling's rendering with Lite's chart idioms:
ChartStyle/ChartHoverHelper,SeriesColors/ChartPaletteidentities,UtcOffsetMinutesdisplay conversion, Y-floor-at-0, window-pinnedSetLimitsX, connected-scatter padded to the window ends.Tests
Lite.Tests/BlockingStatsReaderTests.cs— real-DuckDB round-trips that plantblocked_process_reports/dmv_blocking_snapshots/deadlocksrows and assert:GetDeadlockTrendAsyncover the same window.Validation
dotnet build Lite/PerformanceMonitorLite.csproj -c Debug— clean (0 errors).Lite.Tests— 1238 passed, 0 failed (includes the new 7 + the collector-coverage pin, which is unchanged: no new collector table).Darling.Testsnot required.🤖 Generated with Claude Code