[needs visual review] #1138 FinOps index/object heatmap redesign (both phases, both apps)#1237
Merged
Merged
Conversation
Replace the standalone Object Sizes & Growth (#5) and Index Usage (#6) FinOps tabs with a Storage Growth (#4) parent -> object -> index drill: - Storage Growth grid: double-click a database row (or "Show objects") drills to that DB's object-growth heatmap (rows = top-N objects by reserved-MB growth over the window, X = daily buckets, color = absolute reserved MB) plus a companion per-object grid; double-click an object drills to its per-index size + usage. Back/breadcrumb navigation; an in-UI substrate caveat (object reservation vs file allocation). - Shared foundations so both apps render identically (no drift): pure PerformanceMonitor.Common/FinOpsHeatmap (top-N ranking, long->matrix pivot, per-column log color-scale); PerformanceMonitor.Ui/FinOpsHeatmapRenderer (the query-heatmap renderer with count couplings stripped: MB colorbar, M/d axis); PerformanceMonitor.Ui/HeatIntensityToBrushConverter (themed cell shading, used by Phase 2). - Read layer (both apps): GetObjectGrowthHeatmapDataAsync ranks the top-N cheaply (2-snapshot diff) then series-scans only those, DB-scoped on the covering index lead column to avoid the #1135 uncovered scan; GetObjectIndexDetailAsync for the index leaf. Existing GetObjectSizeGrowthAsync / GetIndexUsageAsync stay for MCP. - Tests: FinOpsHeatmapBuilder ranking + long->matrix pivot, in both test projects. #7 Locking & Contention is untouched here (it is Phase 2's home). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dex drill (both apps) Turn the Locking & Contention tab into a heatmap-in-grid: the four *_wait_in_ms cells are shaded per-column (log scale, max=0 guarded) by their wait category's hue (row/page lock = Lock, page latch = Buffer Latch, page-io-latch = Buffer IO) via the shared HeatIntensityToBrushConverter, with the numeric values still visible. Cumulative snapshot, no delta (plan 3B), so this sidesteps the M1/M2 issues a lock-wait-over-time chart would hit. - DB selector (per-database latest, so "all databases" shows every DB's newest row); double-click an index -> full lock/latch counters + identity, with back. - Read layer (both apps): GetIndexLockingAsync gains an optional database filter, a per-database-latest CTE, and the two latch *_count columns; new GetIndexLockingDatabasesAsync feeds the selector. Existing no-arg call kept for MCP. - Fix the R7 doc-drift: install/02, install/55, and the Lite collector header all claimed lock-wait deltas are "computed in the read layer" - no such logic exists and M1 shows it would not be safe; corrected to "raw cumulative totals, no delta". - Tests: ColumnLogIntensities (the per-column color-scale math) in both projects; Lite integration tests for the object-growth producer, the index detail, and the locking DB selector/filter. Review fixes folded in: deterministic ORDER BY tiebreaker on the object-growth ranking so Lite's two queries (and Dashboard/Lite) always pick the same top-N set and order; the heatmap rows + companion grid now share one ranking authority (FinOpsHeatmapBuilder.RankTopGrowers); T-SQL polish on the Phase-1 producer (COUNT_BIG, unique clustered #ranked, TABLOCK, OPTION hints, CONVERT). All new T-SQL validated live against a real PerformanceMonitor database. 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.
Implements #1138 — the FinOps index/object heatmap redesign, both phases, both apps (Dashboard + Lite), on existing collected data. Follows the 3-review-round plan in
plans/finops-index-heatmap-redesign.md.This PR is code-complete but needs your visual sign-off — I cannot launch the apps from the worktree (single-instance would evict your running Dashboard/Lite and kill the MCP servers), so the heatmap rendering, cell shading, and drill navigation need an eyes-on pass. The code itself is done: both apps build green, tests pass, and all new T-SQL was validated live against a real
PerformanceMonitordatabase (SQL2025).Phase 1 — Object-growth heatmap + Storage Growth drill
Replaces the two flat tabs Object Sizes & Growth (#5, removed) and Index Usage (#6, folded) with a drill rooted at Storage Growth (#4):
(database, schema, table)(plan K1).Phase 2 — Locking color-scaled wait-type grid + drill
Turns Locking & Contention (#7) into a heatmap-in-grid (plan §3B — not a ScottPlot heatmap, so no M1/M2 issues):
*_wait_in_mscells are shaded per-column (log scale, max=0 guarded) by their wait category's hue — row/page lock = Lock, page latch = Buffer Latch, page-io-latch = Buffer IO — via a shared themed value→brush converter. The numeric values stay visible in every cell.*_countcolumns; a newGetIndexLockingDatabasesAsyncfeeds the selector.install/02,install/55, and the Lite collector header all claimed lock-wait deltas are "computed in the read layer" — no such logic exists and M1 shows it wouldn't be safe; corrected to "raw cumulative totals, no delta".Shared / parity
To keep the two hand-duplicated apps from drifting, the parity-critical logic is shared once:
PerformanceMonitor.Common/FinOpsHeatmap.cs— pure ranking, long→matrix pivot, per-column log color-scale.PerformanceMonitor.Ui/FinOpsHeatmapRenderer.cs— the query-heatmap renderer with count couplings stripped (MB colorbar,M/daxis).PerformanceMonitor.Ui/HeatIntensityToBrushConverter.cs— themed cell shading.Tests
Reviewer-driven fixes already folded in
ORDER BYtiebreaker on the growth ranking so Lite's two queries (and Dashboard vs Lite) always pick the same top-N set + order; the heatmap rows and companion grid now share one ranking authority.COUNT_BIG, unique-clustered#ranked,TABLOCK,OPTIONhints,CONVERToverCAST).Not in this PR
No merge — the only thing gating merge is your visual sign-off. No newly collected columns (read-layer + UI only). The other adjacent tabs (#8 Database Sizes is per-file, #9/#10/#11) are unchanged per the plan's scope.
🤖 Generated with Claude Code