feat(status): add KPI stat strip to the Health tab - #1506
Conversation
Adds a row of five stat tiles above the Health tab's panel grid — CPU (p95, harper+user scopes summed), heap used, main-thread utilization, error rate, and request p95 — so "is anything wrong right now?" reads at a glance. Each tile shows the latest-bucket cluster value, a delta vs the previous window of equal length (arrow + %, up-is-bad coloring), and an axis-less inline-SVG sparkline of the current window; em-dash + no delta when data is absent, skeletons while loading. Tiles reuse useAnalyticsRecords + runPipeline: the current-window fetch passes exactly the panels' arguments so it lands on their existing query key (react-query dedupes to one POST); the shifted previous-window query is the only new key — at most one extra get_analytics POST per metric per window slide, and it shares the key prefix StatusTabs' in-flight refresh guard scans. The error-rate tile projects 1 − total/count per record under count-weighted-mean, which collapses algebraically to the Σ-correct (Σcount − Σtotal)/Σcount — same arithmetic as the derived error-rate panel. Fixes #1457 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UZEaYdKFXuQw2Hf6XpPdEV
There was a problem hiding this comment.
Code Review
This pull request introduces a new KpiStrip component to the HealthTab of the instance status analytics page, displaying five vital metrics (CPU, Heap used, Main thread, Error rate, and Request p95) as KPI tiles with latest values, delta comparisons, and inline SVG sparklines. Feedback suggests optimizing the sparkline component by conditionally rendering the first path only when there are more than two points to avoid redundant SVG elements. Additionally, it is recommended to improve the delta row's accessibility by adding a proper ARIA role and to refine the formatting of flat percentage values to prevent displaying signed zero percentages.
… and prev-window caching - CPU tile: constrain the scope sum to the harper/user dims via a new includeDims on KpiTileDef. The profiler also emits per-hot-function- location cpu-usage records (>100 hits at one location) whose samples are already counted inside the harper/user scope totals, so summing every 'path' dim double-counted CPU on busy nodes. A bucket missing an expected scope now gaps instead of presenting a partial sum as the total. - Delta: useAnalyticsRecords now exposes isPlaceholderData, and the tile only computes a fresh delta when BOTH windows hold settled (non-placeholder) data, holding the last settled delta otherwise. Previously each refresh tick had a settle-gap where keepPreviousData kept isLoading false while one side still held the older window's rows, so computeDelta paired mismatched windows and flipped the arrow through a bogus near-zero reading. - Previous window: quantize its boundaries to the bucket grid so consecutive refresh ticks within one bucket share a query key and hit the staleTime-Infinity cache (the current-window args stay byte-identical to MetricPanel's). Corrected the dedupe comments to the honest accounting: the success/duration panels live on the unmounted Requests tab, so those two current-window fetches are real POSTs per tick that seed the cache for a Requests visit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UZEaYdKFXuQw2Hf6XpPdEV
|
Pushed cda364e addressing three review findings — each one made the strip more trustworthy, and all three came with regression tests: 1. CPU tile no longer double-counts profiler hot-location records. The cpu-usage metric carries more than the 2. Deltas only compute from settled window pairs. With 3. Honest network accounting + previous-window caching. The dedupe comments (and the PR description) claimed every current-window call dedupes with a panel — true only for the three panels mounted on Health; the Gates: Comment generated by kAIle (Claude Fable 5) |
… empty sparkline path (review) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UZEaYdKFXuQw2Hf6XpPdEV
|
idk, is it possible the analytics stuff is bringing down instances in the free tier? I have a very minimally used free cluster in stage, and I swear when I navigate to the analytics status stuff, it goes down. I'm talking cross PRs. What is this costing us from a performance perspective? Are we solving problems in the UI that should be solved in core, or should be solved in an analytics aggregation service, @kylebernhardy ? |
|
Consolidated the performance / architecture question I raised above into a tracking issue — #1516 — assigned to @kylebernhardy to triage, so it's owned cross-PR rather than living only in this thread. Adding the concrete data point from local review: on a stage instance, switching the Health tab to Last 7 days threw 13× Not calling this a blocker for this PR specifically — it's the broader "how much analytics work belongs in the UI" direction call, now tracked in #1516. |
Summary
Implements #1457 — the Health tab now opens with a row of five stat tiles above the panel grid: CPU (p95), Heap used, Main thread utilization, Error rate, and Request p95. Each tile shows:
formatValuepath the charts use),All five tiles render through one
KpiTilecomponent driven by theKPI_TILESconfig, so the delta / absent-data / skeleton treatment is identical by construction (plus an explicit symmetry test).Review focus — network cost and query keys
Honest per-tick accounting while the Health tab is shown (all five current-window keys use exactly
MetricPanel's arguments — same metric string, the context'stimeRange/bucketMs, no conditions — so keys coincide with the panels' convention):successanddurationpanels live on the (unmounted) Requests tab, so those two are real POSTs — they use the panels' key convention, which means they seed the cache for a Requests visit (staleTime ∞ / gcTime 60s) and are never fetched twice for the same window.floor(startTime / bucketMs) * bucketMs); consecutive refresh ticks within one bucket produce the same query key and hit the staleTime-Infinity cache instead of the network. The current-window args are deliberately NOT quantized (they must stay byte-identical toMetricPanel's).ANALYTICS_QUERY_KEY_PREFIX+ instanceId, soStatusTabs' in-flight refresh guard (queryClient.isFetchingon that prefix) covers all of them.getRawAnalyticsQueryOptions(...)output (the panel convention); a panel-shaped hook next to the tile yields exactly 2 POSTs; the strip issues 5 × 2 POSTs on first paint; and a quantization test asserts ticks within one bucket add no previous-window POST while crossing a boundary adds one.Aggregation notes
harper/userdims viaincludeDims: Harper's profiler also emits per-hot-function-location cpu-usage records (>100 hits at one code location) whose samples are already counted inside the scope totals, so summing everypathdim would double-count CPU on busy nodes. A bucket missing one expected scope gaps rather than presenting a partial sum as the total.1 − total/countper record undercount-weighted-mean(weight = count), which collapses algebraically to the Σ-correct(Σcount − Σtotal)/Σcount— the same arithmetic as the derived error-rate panel, not mean-of-ratios. A test pins the canonical fixture (≈0.0188, not 0.455).last+mean,mean+mean, CWM+CWM).useAnalyticsRecordsexposesisPlaceholderData, and while either window still holdskeepPreviousDatarows during a window slide the tile holds the last settled delta instead of pairing mismatched windows (which flipped the arrow through a bogus near-zero reading each refresh tick).previous = 0with nonzero current renders no delta (undefined relative change),0 → 0reads flat 0%.Testing
kpiMath.test.ts— pure unit tests: collapse (sum/mean, null-drop, ordering,includeDimsexclusion + missing-dim gap), latest/mean, delta math (previous=0, negative baseline, epsilon-flat, non-finite), window labels.kpiTiles.test.ts— per-tile pipeline behavior (Σ-correct error rate, CPU scope sum + hot-location exclusion + missing-scope gap, memory gauge, MTU projection, count-weighted p95) + config symmetry.KpiTile.test.tsx— jsdom: value + delta rendering, absent-data em-dash, previous-window-empty (value without delta), loading skeleton, query-key convention + dedupe, held delta during the placeholder phase (mutation-tested: fails against the ungated delta), previous-window key quantization, sparkline flat/short-series branches, full-strip symmetry.tsc -b,oxlint,dprintall clean.Cross-model reviews (pre-PR, pinned to this diff)
current.datais the frozen EMPTY array and the tile shows a skeleton) and two test-coverage nits, both addressed with added tests.Deferred / notes
text-muted-foreground,text-green,text-destructive,--chart-node-1) that are defined for both themes.Fixes #1457
🤖 Generated with Claude Code
https://claude.ai/code/session_01UZEaYdKFXuQw2Hf6XpPdEV
Comment generated by kAIle (Claude Fable 5)