From a02ce19ea659d04e24824ac7206114b3635145c4 Mon Sep 17 00:00:00 2001 From: William Law Date: Mon, 6 Jul 2026 10:46:08 -0400 Subject: [PATCH 1/2] update UI to reflect new metrics reporting --- report/src/pages/LoadTestDetail.tsx | 315 ++-------------------------- 1 file changed, 19 insertions(+), 296 deletions(-) diff --git a/report/src/pages/LoadTestDetail.tsx b/report/src/pages/LoadTestDetail.tsx index 23009a5..a1bce29 100644 --- a/report/src/pages/LoadTestDetail.tsx +++ b/report/src/pages/LoadTestDetail.tsx @@ -11,11 +11,8 @@ import { useLoadTestResult } from "../utils/useDataSeries"; import { durationToNanos, formatDuration, - formatEthFromWei, - formatGasVerbose, formatGpsVerbose, formatLoadTestTimestamp, - formatPercent, formatTps, } from "../utils/formatters"; import { @@ -24,7 +21,6 @@ import { LatencyStats, LoadTestResult, ObservedWindowMetrics, - TailMetrics, } from "../types"; const formatBlockRange = (range: BlockRange): string => { @@ -119,41 +115,32 @@ const formatObservedWindowRange = ( }; }; -const OBSERVED_WINDOW_TOOLTIP = ( +const RESULTS_TOOLTIP = (

- The clean, first portion of the run, sized to the configured duration. This - mirrors what you witness watching the chain live: sustained TPS over a - period of time. Use this against OKRs like “hit 3k swaps/s on the - chain.” -

-); - -const TAIL_INCLUSION_TOOLTIP = ( -

- Txs that landed in blocks past the observed window. Including them in the - headline would lower TPS and raise block / FB latency, but the data is - critical: it surfaces where inclusion-side optimization is still needed. + Client-to-client end-to-end latency: from the moment a transaction is + submitted via eth_sendRawTransaction to when the client + receives and processes it (seeing its own txHash in a block). This mirrors + what you witness watching the chain live: sustained TPS over a period of + time. Use this against OKRs like “hit 3k swaps/s on the chain.”

); const ObservedWindowSummary = ({ window, + totalSubmitted, }: { window: ObservedWindowMetrics; + totalSubmitted: number; }) => { const blockRange = window.block_range; const windowRange = formatObservedWindowRange(window); return ( - + + - @@ -178,247 +165,6 @@ const ObservedWindowSummary = ({ ); }; -const TailSection = ({ - tail, - totalConfirmed, -}: { - tail: TailMetrics; - totalConfirmed: number; -}) => { - const blockRange = tail.block_range; - const hasReceiptDelay = - tail.block_receipt_delay && - durationToNanos(tail.block_receipt_delay.max) > 0; - - const timePastRows = useMemo( - () => buildLatencyRows(tail.time_past_observed_window), - [tail.time_past_observed_window], - ); - const blockLatencyRows = useMemo( - () => buildLatencyRows(tail.block_latency), - [tail.block_latency], - ); - const receiptDelayRows = useMemo( - () => (hasReceiptDelay ? buildLatencyRows(tail.block_receipt_delay) : []), - [tail.block_receipt_delay, hasReceiptDelay], - ); - const flashblocksRows = useMemo( - () => buildLatencyRows(tail.flashblocks_latency), - [tail.flashblocks_latency], - ); - - if (tail.count === 0) { - return ( - -
- No transactions landed past the observed window - {typeof tail.observed_window_end_block === "number" && ( - <> - {" "} - (boundary: block {tail.observed_window_end_block.toLocaleString()} - ) - - )} - . -
-
- ); - } - - return ( - -
- - - - {typeof tail.observed_window_end_block === "number" && ( - - )} - {blockRange && ( - - )} - - -
-

- Time past observed window -

- -
- -
-

- Block latency (tail) -

- -
- - {hasReceiptDelay && ( -
-

- Block receipt delay (tail) -

- -
- )} - -
-

- Flashblocks latency (tail) ·{" "} - {tail.flashblocks_latency.count.toLocaleString()} samples -

- -
-
-
- ); -}; - -const FullRunBaselineSection = ({ result }: { result: LoadTestResult }) => { - const submitted = result.throughput.total_submitted; - const confirmed = result.throughput.total_confirmed; - const failed = result.throughput.total_failed; - const reverted = result.throughput.total_reverted; - const blockRange = result.block_range; - - const blockLatencyRows = useMemo( - () => buildLatencyRows(result.block_latency), - [result.block_latency], - ); - const flashblocksRows = useMemo( - () => buildLatencyRows(result.flashblocks_latency), - [result.flashblocks_latency], - ); - const receiptDelayRows = useMemo( - () => - result.block_receipt_delay - ? buildLatencyRows(result.block_receipt_delay) - : [], - [result.block_receipt_delay], - ); - - return ( -
- - Full-run baseline (observed window + tail combined) - -
-

- Full-run averages dilute the clean reporting window with tail - stragglers. Use the observed-window numbers above for headline - comparisons; this section is included for completeness. -

- - - - - - - {reverted > 0 && ( - - )} - - - - - {blockRange && ( - - )} - - -
-

- Block latency (full run) -

- -
- - {result.block_receipt_delay && ( -
-

- Block receipt delay (full run) -

- -
- )} - -
-

- Flashblocks latency (full run) ·{" "} - {result.flashblocks_latency.count.toLocaleString()} samples -

- -
-
-
- ); -}; - interface LoadTestReportContentProps { result: LoadTestResult; title: string; @@ -436,7 +182,6 @@ export const LoadTestReportContent = ({ backLink, }: LoadTestReportContentProps) => { const observedWindow = result.observed_window; - const tail = result.tail ?? undefined; // Headline numbers come from observed_window when available, otherwise fall // back to the legacy full-run fields so older S3 runs still render. @@ -445,8 +190,6 @@ export const LoadTestReportContent = ({ observedWindow?.block_latency ?? result.block_latency; const headlineFlashblocksLatency = observedWindow?.flashblocks_latency ?? result.flashblocks_latency; - const headlineReceiptDelay = - observedWindow?.block_receipt_delay ?? result.block_receipt_delay; const headlineBlockLatencyRows = useMemo( () => buildLatencyRows(headlineBlockLatency), @@ -456,13 +199,8 @@ export const LoadTestReportContent = ({ () => buildLatencyRows(headlineFlashblocksLatency), [headlineFlashblocksLatency], ); - const headlineReceiptDelayRows = useMemo( - () => (headlineReceiptDelay ? buildLatencyRows(headlineReceiptDelay) : []), - [headlineReceiptDelay], - ); const headlineLabel = observedWindow ? "Observed-window TPS" : "Swaps/s"; - const latencyScopeLabel = observedWindow ? "observed window" : "full run"; return ( <> @@ -498,28 +236,22 @@ export const LoadTestReportContent = ({ {result.config && } - {observedWindow && } + {observedWindow && ( + + )} - + - {headlineReceiptDelay && ( - - - - )} - - {tail && ( - - )} - {(() => { const reverted = result.throughput.total_reverted; @@ -562,8 +287,6 @@ export const LoadTestReportContent = ({ ); })()} - - {observedWindow && } ); }; From c86fc34abbfa5c835ffd0be829484a61a6e4acdb Mon Sep 17 00:00:00 2001 From: William Law Date: Mon, 6 Jul 2026 10:59:23 -0400 Subject: [PATCH 2/2] update export interface --- report/src/pages/LoadTestDetail.tsx | 80 +++++++---------------------- report/src/types.ts | 65 ++++------------------- 2 files changed, 29 insertions(+), 116 deletions(-) diff --git a/report/src/pages/LoadTestDetail.tsx b/report/src/pages/LoadTestDetail.tsx index a1bce29..d910d7d 100644 --- a/report/src/pages/LoadTestDetail.tsx +++ b/report/src/pages/LoadTestDetail.tsx @@ -20,7 +20,6 @@ import { FlashblocksLatencyStats, LatencyStats, LoadTestResult, - ObservedWindowMetrics, } from "../types"; const formatBlockRange = (range: BlockRange): string => { @@ -96,25 +95,6 @@ const SwapsPerSecondHero = ({ tps, label }: { tps: number; label: string }) => ( ); -// The full observed-window block range, matching the CLI's display: -// `first_block ..= first_block + expected_block_count - 1`. The -// `window.block_range` field is the range of blocks that actually contained -// confirmed test txs and is typically smaller — surfaced as a hint. -const formatObservedWindowRange = ( - window: ObservedWindowMetrics, -): { value: string; hint: string } | null => { - const first = window.block_range.first_block; - if (typeof first !== "number" || window.expected_block_count === 0) { - return null; - } - const end = first + window.expected_block_count - 1; - const confirmedCount = window.block_range.block_count; - return { - value: `${first.toLocaleString()} → ${end.toLocaleString()}`, - hint: `${window.expected_block_count.toLocaleString()} blocks · txs landed in ${confirmedCount.toLocaleString()}`, - }; -}; - const RESULTS_TOOLTIP = (

Client-to-client end-to-end latency: from the moment a transaction is @@ -125,40 +105,28 @@ const RESULTS_TOOLTIP = (

); -const ObservedWindowSummary = ({ - window, - totalSubmitted, -}: { - window: ObservedWindowMetrics; - totalSubmitted: number; -}) => { - const blockRange = window.block_range; - const windowRange = formatObservedWindowRange(window); +const ResultsSummary = ({ result }: { result: LoadTestResult }) => { + const { throughput, block_range: blockRange } = result; return ( - + - - - {windowRange ? ( + + + {blockRange && ( - ) : ( - blockRange && ( - - ) )} @@ -181,26 +149,19 @@ export const LoadTestReportContent = ({ subtitle, backLink, }: LoadTestReportContentProps) => { - const observedWindow = result.observed_window; - - // Headline numbers come from observed_window when available, otherwise fall - // back to the legacy full-run fields so older S3 runs still render. - const headlineTps = observedWindow?.tps ?? result.throughput.tps; - const headlineBlockLatency = - observedWindow?.block_latency ?? result.block_latency; - const headlineFlashblocksLatency = - observedWindow?.flashblocks_latency ?? result.flashblocks_latency; + const headlineTps = result.throughput.tps; + const headlineFlashblocksLatency = result.flashblocks_latency; const headlineBlockLatencyRows = useMemo( - () => buildLatencyRows(headlineBlockLatency), - [headlineBlockLatency], + () => buildLatencyRows(result.block_latency), + [result.block_latency], ); const headlineFlashblocksRows = useMemo( () => buildLatencyRows(headlineFlashblocksLatency), [headlineFlashblocksLatency], ); - const headlineLabel = observedWindow ? "Observed-window TPS" : "Swaps/s"; + const headlineLabel = "Swaps/s"; return ( <> @@ -236,12 +197,7 @@ export const LoadTestReportContent = ({ {result.config && } - {observedWindow && ( - - )} + observed_window_end_block`). `null` on continuous runs - * (no configured duration). Producer added in base/base#3358. - */ -export interface TailMetrics { - observed_window_end_block: number | null; - count: number; - confirmed_pct: number; - block_range: BlockRange; - time_past_observed_window: LatencyStats; - block_latency: LatencyStats; - block_receipt_delay: LatencyStats; - flashblocks_latency: FlashblocksLatencyStats; -} - +// Mirrors Rust `MetricsSummary` (base/base#3695). Reports client-to-client +// end-to-end latency over the full run; the earlier observed-window/tail split +// and per-tx block_receipt_delay were removed. export interface LoadTestResult { + // Present only on runs where a fatal error stopped the test. + error?: string; block_latency: LatencyStats; - // Submit-to-receipt-observation delay, full-run baseline. Optional for - // back-compat: producer added in base/base#3358. - block_receipt_delay?: LatencyStats; flashblocks_latency: FlashblocksLatencyStats; throughput: ThroughputStats; throughput_percentiles: ThroughputPercentiles; + throughput_timeseries: ThroughputSample[]; gas: GasStats; + block_range: BlockRange; // Element type is best-effort until upgrades.md P3 #7 lands. Empty arrays // dominate today, so we have no live samples to verify against. top_failure_reasons: FailureReason[]; - // Both optional for back-compat: older S3 runs predate these fields and the - // page must render without them. Sections that depend on each field are - // gated on its presence rather than rendering empty placeholders. + // Optional for back-compat: older S3 runs predate this field, and the page + // omits the config card when absent. config?: LoadTestConfig; - throughput_timeseries?: ThroughputSample[]; - // Optional for back-compat: older runs predate this field. The summary - // section gates the block range stats on its presence. - block_range?: BlockRange; - // Observed reporting window (clean TPS / latency). Optional for back-compat: - // older S3 runs predate this; the page falls back to full-run fields. - observed_window?: ObservedWindowMetrics; - // Inclusion-delay tail. `null` on continuous runs; `undefined` on older - // runs that predate the field. - tail?: TailMetrics | null; } /**