From 1fa4cd64ab4564342fd8e2ebb0112419bc51465e Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Mon, 20 Jul 2026 12:10:17 -0700 Subject: [PATCH] fix(report): render charts for single-role runs and missing validator metrics The run-comparison charts page assumed every run had both sequencer and validator metrics. For sequencer-only runs (no metrics-validator.json) two things broke: - ChartSelector fabricated a validator series for every run; fetching its missing metrics 404'd and rejected the whole Promise.all batch, blanking the page. It now emits a role series only when that role's metrics exist, and useMultipleDataSeries degrades an individual failed fetch to an empty series instead of failing the batch. - Grouping fell back to the 'role' dimension, which collapses to a single value when only one role is present, so it was dropped from the available variables. The default then pointed at an unavailable dimension and the role memo threw on variables.role[0]. useBenchmarkFilters now falls back to the first available variable (e.g. TransactionPayload) and guards the role lookup, so you can compare by transaction payload with a single role. --- report/src/components/ChartSelector.tsx | 39 ++++++++++++++++------- report/src/hooks/useBenchmarkFilters.ts | 41 +++++++++++++++++++++---- report/src/pages/RunComparison.tsx | 3 +- report/src/utils/useDataSeries.ts | 24 ++++++++++----- 4 files changed, 81 insertions(+), 26 deletions(-) diff --git a/report/src/components/ChartSelector.tsx b/report/src/components/ChartSelector.tsx index cd9d4666..22f937f4 100644 --- a/report/src/components/ChartSelector.tsx +++ b/report/src/components/ChartSelector.tsx @@ -1,5 +1,5 @@ import { useEffect, useMemo, useRef } from "react"; -import { BenchmarkRuns } from "../types"; +import { BenchmarkRun, BenchmarkRuns } from "../types"; import { isEqual } from "lodash"; import { camelToTitleCase, @@ -47,10 +47,26 @@ const ChartSelector = ({ const runsWithRoles = useMemo( () => - benchmarkRuns.runs.flatMap((r) => [ - { ...r, testConfig: { ...r.testConfig, role: "sequencer" } }, - { ...r, testConfig: { ...r.testConfig, role: "validator" } }, - ]), + benchmarkRuns.runs.flatMap((r) => { + // Only expose a role variant when that role actually produced metrics. + // Sequencer-only runs have no metrics-validator.json, and fetching a + // missing role 404s and rejects the whole chart batch, so emitting a + // phantom validator variant would blank the charts entirely. + const variants: BenchmarkRun[] = []; + if (r.result?.sequencerMetrics) { + variants.push({ + ...r, + testConfig: { ...r.testConfig, role: "sequencer" }, + }); + } + if (r.result?.validatorMetrics) { + variants.push({ + ...r, + testConfig: { ...r.testConfig, role: "validator" }, + }); + } + return variants; + }), [benchmarkRuns.runs], ); @@ -59,6 +75,7 @@ const ChartSelector = ({ filterOptions, matchedRuns, filterSelections, + byMetric, setFilters, setByMetric, role, @@ -69,7 +86,7 @@ const ChartSelector = ({ useEffect(() => { let colorMap: ((val: number) => string) | undefined = undefined; - if (filterSelections.byMetric === "GasLimit" && matchedRuns.length > 0) { + if (byMetric === "GasLimit" && matchedRuns.length > 0) { const gasLimits = matchedRuns.map((r) => Number(r.testConfig.GasLimit)); const min = Math.min(...gasLimits); const max = Math.max(...gasLimits); @@ -87,9 +104,9 @@ const ChartSelector = ({ let seriesName: string; let color: string | undefined = undefined; - const byMetricValue = run.testConfig[filterSelections.byMetric]; + const byMetricValue = run.testConfig[byMetric]; - if (filterSelections.byMetric === "GasLimit") { + if (byMetric === "GasLimit") { const gasLimitNum = Number(byMetricValue); seriesName = formatValue(gasLimitNum, "gas"); color = colorMap?.(gasLimitNum); @@ -119,7 +136,7 @@ const ChartSelector = ({ lastSentDataRef.current = dataToSend; onChangeDataQuery({ data: dataToSend, role }); } - }, [matchedRuns, filterSelections.byMetric, role, onChangeDataQuery]); + }, [matchedRuns, byMetric, role, onChangeDataQuery]); return (
@@ -127,7 +144,7 @@ const ChartSelector = ({
Show Line Per