diff --git a/src/components/latency-chart.test.tsx b/src/components/latency-chart.test.tsx
index 3ca51ba..136aec1 100644
--- a/src/components/latency-chart.test.tsx
+++ b/src/components/latency-chart.test.tsx
@@ -367,6 +367,32 @@ describe('latency chart on sample data', () => {
}
})
+ it('agrees with the p95 tile, as a live platform would', () => {
+ // On a platform the tile and the chart's newest point are one number. The demo
+ // used to print 88 ms on the tile beside a curve ending in the 40s — sample
+ // data, but a false lesson about what the two panels mean.
+ const restoreEventSource = installFakeEventSource()
+ vi.useFakeTimers()
+ try {
+ const { result } = renderHook(() => useConsoleData({ sampleDelayMs: 500 }))
+ act(() => {
+ vi.advanceTimersByTime(600) // no platform answered: the demo takes over
+ })
+ expect(result.current.conn.status).toBe('sample')
+ const { latency, summary } = result.current.data!
+ const newest = latency[latency.length - 1]
+ const windowBack = latency.findLast((p) => p.at <= newest.at - summary!.windowMs)!
+ expect(summary!.p95LatencyMs).toBe(newest.p95)
+ expect(summary!.p95DeltaMs).toBe(newest.p95 - windowBack.p95)
+
+ const { getByText } = render()
+ expect(getByText(String(newest.p95))).toBeTruthy()
+ } finally {
+ vi.useRealTimers()
+ restoreEventSource()
+ }
+ })
+
it('drops the label once real samples replace it', () => {
const { queryByText, rerender } = render()
rerender()
diff --git a/src/hooks/use-console-data.ts b/src/hooks/use-console-data.ts
index 812abf9..0397080 100644
--- a/src/hooks/use-console-data.ts
+++ b/src/hooks/use-console-data.ts
@@ -166,12 +166,13 @@ function int(v: unknown): number | null {
}
function mockData(now: number): LiveData {
+ const latency = mockLatencySeries(now)
return {
traces: mockTraces(now),
metrics: mockMetrics(now),
modules: mockModules(),
- summary: mockSummary(),
- latency: mockLatencySeries(now),
+ summary: mockSummary(latency),
+ latency,
}
}
diff --git a/src/lib/mock.ts b/src/lib/mock.ts
index c3c4943..6a18f40 100644
--- a/src/lib/mock.ts
+++ b/src/lib/mock.ts
@@ -123,19 +123,28 @@ export function mockModules(): ModuleStatus[] {
// Windowed KPI header aggregate, mirroring the platform `summary` SSE event.
// Trends are populated (not null) so the sample demo shows the fully-wired header.
-export function mockSummary(): TraceSummary {
+//
+// The p95 and its trend are read off the sample latency series rather than made up
+// beside it. On a real platform the p95 tile and the chart's newest point are the
+// same number, and a demo that showed them disagreeing would teach the wrong thing
+// about the screen — sample data is still a claim about how the console behaves.
+export function mockSummary(latency: readonly LatencyPoint[]): TraceSummary {
+ const windowMs = 60000
+ const newest = latency[latency.length - 1]
+ // The point one window back is what the platform compares against.
+ const prev = latency.findLast((p) => p.at <= newest.at - windowMs) ?? latency[0]
return {
- windowMs: 60000,
+ windowMs,
count: 512,
errorCount: 7,
errorRate: 0.0137,
p50LatencyMs: 12,
- p95LatencyMs: 88,
+ p95LatencyMs: newest.p95,
p99LatencyMs: 210,
maxLatencyMs: 640,
requestsDeltaPct: 0.12,
errorRateDeltaPp: 0.31,
- p95DeltaMs: -6,
+ p95DeltaMs: newest.p95 - prev.p95,
activeModules: 6,
modulesByMode: { worker: 3, container: 1, 'in-process': 2 },
}