diff --git a/report/src/components/ChartGrid.tsx b/report/src/components/ChartGrid.tsx index 217e1a22..562b5bc7 100644 --- a/report/src/components/ChartGrid.tsx +++ b/report/src/components/ChartGrid.tsx @@ -5,12 +5,16 @@ import LineChart from "./LineChart"; interface ProvidedProps { data: DataSeries[]; + role: "sequencer" | "validator" | null; } -const ChartGrid: React.FC = ({ data }: ProvidedProps) => { +const ChartGrid: React.FC = ({ data, role }: ProvidedProps) => { return (
{Object.entries(CHART_CONFIG).map(([metricKey, config]) => { + // sequencer and validator have different thresholds + console.log(role, metricKey); + const thresholdKey = role ? `${role}/${metricKey}` : null; const chartData = data.flatMap((s) => s.data); const thresholds = data[0]?.thresholds; const executionMetrics = chartData @@ -32,7 +36,7 @@ const ChartGrid: React.FC = ({ data }: ProvidedProps) => { return (
- +
); })} diff --git a/report/src/components/ChartSelector.tsx b/report/src/components/ChartSelector.tsx index 36018a88..cd9d4666 100644 --- a/report/src/components/ChartSelector.tsx +++ b/report/src/components/ChartSelector.tsx @@ -24,9 +24,19 @@ export interface SelectedData { interface ChartSelectorProps { benchmarkRuns: BenchmarkRuns; - onChangeDataQuery: (data: SelectedData[]) => void; + onChangeDataQuery: (data: DataSelection) => void; } +export interface DataSelection { + data: SelectedData[]; + role: "sequencer" | "validator" | null; +} + +export const EmptyDataSelection: DataSelection = { + data: [], + role: null, +}; + const ChartSelector = ({ benchmarkRuns, onChangeDataQuery, @@ -51,6 +61,7 @@ const ChartSelector = ({ filterSelections, setFilters, setByMetric, + role, } = useBenchmarkFilters(runsWithRoles, "role"); const lastSentDataRef = useRef([]); @@ -106,9 +117,9 @@ const ChartSelector = ({ if (!isEqual(dataToSend, lastSentDataRef.current)) { lastSentDataRef.current = dataToSend; - onChangeDataQuery(dataToSend); + onChangeDataQuery({ data: dataToSend, role }); } - }, [matchedRuns, filterSelections.byMetric, onChangeDataQuery]); + }, [matchedRuns, filterSelections.byMetric, role, onChangeDataQuery]); return (
diff --git a/report/src/components/LineChart.tsx b/report/src/components/LineChart.tsx index 442a2c5d..a2c0c3af 100644 --- a/report/src/components/LineChart.tsx +++ b/report/src/components/LineChart.tsx @@ -16,6 +16,7 @@ import { isEqual } from "lodash"; interface LineChartProps { series: DataSeries[]; + thresholdKey: string | null; metricKey: string; title?: string; description?: string; @@ -48,6 +49,7 @@ const MAX_TICKS = 10; const LineChart: React.FC = ({ series, + thresholdKey, metricKey, title, description, @@ -342,14 +344,14 @@ const LineChart: React.FC = ({ const maxThreshold = useMemo(() => { let maxThreshold = 0; for (const thresholdMap of [thresholds?.warning, thresholds?.error]) { - if (thresholdMap) { - if (thresholdMap[metricKey] > maxThreshold) { - maxThreshold = thresholdMap[metricKey]; + if (thresholdMap && thresholdKey) { + if (thresholdMap[thresholdKey] > maxThreshold) { + maxThreshold = thresholdMap[thresholdKey]; } } } return maxThreshold; - }, [thresholds, metricKey]); + }, [thresholds, thresholdKey]); return ( = ({ // Add warning threshold line (yellow) if ( thresholds.warning && - thresholds.warning[metricKey] !== undefined + thresholdKey && + thresholds.warning[thresholdKey] !== undefined ) { - const warningY = y(thresholds.warning[metricKey]); + const warningY = y(thresholds.warning[thresholdKey]); svg .append("line") .attr("class", "threshold-line warning") @@ -425,8 +428,12 @@ const LineChart: React.FC = ({ } // Add error threshold line (red) - if (thresholds.error && thresholds.error[metricKey] !== undefined) { - const errorY = y(thresholds.error[metricKey]); + if ( + thresholds.error && + thresholdKey && + thresholds.error[thresholdKey] !== undefined + ) { + const errorY = y(thresholds.error[thresholdKey]); svg .append("line") .attr("class", "threshold-line error") diff --git a/report/src/components/RunList.tsx b/report/src/components/RunList.tsx index 52b5db6c..0265129b 100644 --- a/report/src/components/RunList.tsx +++ b/report/src/components/RunList.tsx @@ -135,9 +135,9 @@ const RunList = ({ // Handle threshold displays for specific columns if (column === "getPayload") { const warningThreshold = - (run.thresholds?.warning?.["latency/get_payload"] ?? 0) / 1e9; + (run.thresholds?.warning?.["sequencer/latency/get_payload"] ?? 0) / 1e9; const errorThreshold = - (run.thresholds?.error?.["latency/get_payload"] ?? 0) / 1e9; + (run.thresholds?.error?.["sequencer/latency/get_payload"] ?? 0) / 1e9; return ( { + if (filterSelections.byMetric === "role") { + return null; + } + + return ( + (filterSelections.params.role as "sequencer" | "validator") ?? + variables.role[0] + ); + }, [filterSelections.byMetric, filterSelections.params.role, variables]); + return { variables, filterOptions, @@ -103,5 +115,6 @@ export function useBenchmarkFilters( filterSelections, // Return current selections for UI binding setFilters, // Return the simplified setter setByMetric, + role, }; } diff --git a/report/src/pages/RunComparison.tsx b/report/src/pages/RunComparison.tsx index c8572c34..03b853d2 100644 --- a/report/src/pages/RunComparison.tsx +++ b/report/src/pages/RunComparison.tsx @@ -1,5 +1,8 @@ import { useMemo, useState } from "react"; -import ChartSelector, { SelectedData } from "../components/ChartSelector"; +import ChartSelector, { + DataSelection, + EmptyDataSelection, +} from "../components/ChartSelector"; import ChartGrid from "../components/ChartGrid"; import { useTestMetadata, useMultipleDataSeries } from "../utils/useDataSeries"; import { DataSeries } from "../types"; @@ -13,7 +16,7 @@ function RunComparison() { throw new Error("Benchmark run ID is required"); } - const [selection, setSelection] = useState([]); + const [selection, setSelection] = useState(EmptyDataSelection); const { data: allBenchmarkRuns, isLoading: isLoadingBenchmarkRuns } = useTestMetadata(); @@ -42,7 +45,7 @@ function RunComparison() { }, [allBenchmarkRuns, benchmarkRunId]); const dataQueryKey = useMemo(() => { - return selection.map((query) => { + return selection.data.map((query) => { // Find the run that matches this outputDir to get the runId const run = benchmarkRuns.runs.find( (r) => r.outputDir === query.outputDir, @@ -50,7 +53,7 @@ function RunComparison() { const runId = run?.id || query.outputDir; // Fallback to outputDir if no ID found return [runId, query.outputDir, query.role] as [string, string, string]; }); - }, [selection, benchmarkRuns]); + }, [selection.data, benchmarkRuns]); const { data: dataPerFile, isLoading } = useMultipleDataSeries(dataQueryKey); const data = useMemo(() => { @@ -59,15 +62,15 @@ function RunComparison() { } return dataPerFile.map((data, index): DataSeries => { - const { name, color } = selection[index]; + const { name, color } = selection.data[index]; return { name, data, color, - thresholds: selection[index].thresholds, + thresholds: selection.data[index].thresholds, }; }); - }, [dataPerFile, selection]); + }, [dataPerFile, selection.data]); if (!benchmarkRuns || isLoadingBenchmarkRuns) { return
Loading...
; @@ -82,7 +85,11 @@ function RunComparison() { onChangeDataQuery={setSelection} benchmarkRuns={benchmarkRuns} /> - {isLoading ? "Loading..." : } + {isLoading ? ( + "Loading..." + ) : ( + + )}