feat: migrate agent charts to ThemedChart + Recharts
Replace custom LineChart/AreaChart/BarChart usage with ThemedChart wrapper. Data format changed from ChartSeries[] to Recharts-native flat objects. Uses DS v0.1.47. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,9 +8,12 @@ import {
|
||||
DataTable,
|
||||
EmptyState,
|
||||
Tabs,
|
||||
AreaChart,
|
||||
LineChart,
|
||||
BarChart,
|
||||
ThemedChart,
|
||||
Area,
|
||||
Line,
|
||||
Bar,
|
||||
ReferenceLine,
|
||||
CHART_COLORS,
|
||||
RouteFlow,
|
||||
Spinner,
|
||||
MonoText,
|
||||
@@ -752,44 +755,31 @@ export default function RouteDetail() {
|
||||
<div className={styles.chartGrid} style={{ marginTop: 16 }}>
|
||||
<div className={chartCardStyles.chartCard}>
|
||||
<div className={styles.chartTitle}>Throughput</div>
|
||||
<AreaChart
|
||||
series={[{
|
||||
label: 'Throughput',
|
||||
data: chartData.map((d, i) => ({ x: i, y: d.throughput })),
|
||||
}]}
|
||||
height={200}
|
||||
/>
|
||||
<ThemedChart data={chartData} height={200} xDataKey="time" yLabel="msg/s">
|
||||
<Area dataKey="throughput" name="Throughput" stroke={CHART_COLORS[0]}
|
||||
fill={CHART_COLORS[0]} fillOpacity={0.1} strokeWidth={2} dot={false} />
|
||||
</ThemedChart>
|
||||
</div>
|
||||
<div className={chartCardStyles.chartCard}>
|
||||
<div className={styles.chartTitle}>Latency</div>
|
||||
<LineChart
|
||||
series={[{
|
||||
label: 'Latency',
|
||||
data: chartData.map((d, i) => ({ x: i, y: d.latency })),
|
||||
}]}
|
||||
height={200}
|
||||
threshold={{ value: 300, label: 'SLA 300ms' }}
|
||||
/>
|
||||
<ThemedChart data={chartData} height={200} xDataKey="time" yLabel="ms">
|
||||
<Line dataKey="latency" name="Latency" stroke={CHART_COLORS[0]} strokeWidth={2} dot={false} />
|
||||
<ReferenceLine y={300} stroke="var(--error)" strokeDasharray="5 3"
|
||||
label={{ value: 'SLA 300ms', position: 'right', fill: 'var(--error)', fontSize: 9 }} />
|
||||
</ThemedChart>
|
||||
</div>
|
||||
<div className={chartCardStyles.chartCard}>
|
||||
<div className={styles.chartTitle}>Errors</div>
|
||||
<BarChart
|
||||
series={[{
|
||||
label: 'Errors',
|
||||
data: chartData.map((d) => ({ x: d.time, y: d.errors })),
|
||||
}]}
|
||||
height={200}
|
||||
/>
|
||||
<ThemedChart data={chartData} height={200} xDataKey="time" yLabel="errors">
|
||||
<Bar dataKey="errors" name="Errors" fill={CHART_COLORS[1]} />
|
||||
</ThemedChart>
|
||||
</div>
|
||||
<div className={chartCardStyles.chartCard}>
|
||||
<div className={styles.chartTitle}>Success Rate</div>
|
||||
<AreaChart
|
||||
series={[{
|
||||
label: 'Success Rate',
|
||||
data: chartData.map((d, i) => ({ x: i, y: d.successRate })),
|
||||
}]}
|
||||
height={200}
|
||||
/>
|
||||
<ThemedChart data={chartData} height={200} xDataKey="time" yLabel="%">
|
||||
<Area dataKey="successRate" name="Success Rate" stroke={CHART_COLORS[0]}
|
||||
fill={CHART_COLORS[0]} fillOpacity={0.1} strokeWidth={2} dot={false} />
|
||||
</ThemedChart>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -3,9 +3,12 @@ import { useParams, useNavigate } from 'react-router';
|
||||
import {
|
||||
KpiStrip,
|
||||
DataTable,
|
||||
AreaChart,
|
||||
LineChart,
|
||||
BarChart,
|
||||
ThemedChart,
|
||||
Area,
|
||||
Line,
|
||||
Bar,
|
||||
ReferenceLine,
|
||||
CHART_COLORS,
|
||||
Card,
|
||||
Sparkline,
|
||||
MonoText,
|
||||
@@ -243,41 +246,17 @@ export default function RoutesMetrics() {
|
||||
[timeseries],
|
||||
);
|
||||
|
||||
// Chart series from timeseries buckets
|
||||
const throughputChartSeries = useMemo(() => [{
|
||||
label: 'Throughput',
|
||||
data: (timeseries?.buckets || []).map((b, i) => ({
|
||||
x: i as number,
|
||||
y: b.totalCount,
|
||||
// Flat chart data from timeseries buckets
|
||||
const chartData = useMemo(() =>
|
||||
(timeseries?.buckets || []).map((b, i) => ({
|
||||
idx: i,
|
||||
throughput: b.totalCount,
|
||||
latency: b.avgDurationMs,
|
||||
errors: b.failedCount,
|
||||
volume: b.totalCount,
|
||||
})),
|
||||
}], [timeseries]);
|
||||
|
||||
const latencyChartSeries = useMemo(() => [{
|
||||
label: 'Latency',
|
||||
data: (timeseries?.buckets || []).map((b, i) => ({
|
||||
x: i as number,
|
||||
y: b.avgDurationMs,
|
||||
})),
|
||||
}], [timeseries]);
|
||||
|
||||
const errorBarSeries = useMemo(() => [{
|
||||
label: 'Errors',
|
||||
data: (timeseries?.buckets || []).map((b) => {
|
||||
const ts = new Date(b.time);
|
||||
const label = !isNaN(ts.getTime())
|
||||
? ts.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
|
||||
: '—';
|
||||
return { x: label, y: b.failedCount };
|
||||
}),
|
||||
}], [timeseries]);
|
||||
|
||||
const volumeChartSeries = useMemo(() => [{
|
||||
label: 'Volume',
|
||||
data: (timeseries?.buckets || []).map((b, i) => ({
|
||||
x: i as number,
|
||||
y: b.totalCount,
|
||||
})),
|
||||
}], [timeseries]);
|
||||
[timeseries],
|
||||
);
|
||||
|
||||
const kpiItems = useMemo(() =>
|
||||
buildKpiItems(stats, rows.length, throughputSparkline, errorSparkline),
|
||||
@@ -315,42 +294,34 @@ export default function RoutesMetrics() {
|
||||
</div>
|
||||
|
||||
{/* 2x2 chart grid */}
|
||||
{(timeseries?.buckets?.length ?? 0) > 0 && (
|
||||
{chartData.length > 0 && (
|
||||
<div className={styles.chartGrid}>
|
||||
<Card title="Throughput (msg/s)">
|
||||
<AreaChart
|
||||
series={throughputChartSeries}
|
||||
yLabel="msg/s"
|
||||
height={200}
|
||||
className={styles.chart}
|
||||
/>
|
||||
<ThemedChart data={chartData} height={200} xDataKey="idx" yLabel="msg/s">
|
||||
<Area dataKey="throughput" name="Throughput" stroke={CHART_COLORS[0]}
|
||||
fill={CHART_COLORS[0]} fillOpacity={0.1} strokeWidth={2} dot={false} />
|
||||
</ThemedChart>
|
||||
</Card>
|
||||
|
||||
<Card title="Latency (ms)">
|
||||
<LineChart
|
||||
series={latencyChartSeries}
|
||||
yLabel="ms"
|
||||
threshold={{ value: 300, label: 'SLA 300ms' }}
|
||||
height={200}
|
||||
className={styles.chart}
|
||||
/>
|
||||
<ThemedChart data={chartData} height={200} xDataKey="idx" yLabel="ms">
|
||||
<Line dataKey="latency" name="Latency" stroke={CHART_COLORS[0]} strokeWidth={2} dot={false} />
|
||||
<ReferenceLine y={300} stroke="var(--error)" strokeDasharray="5 3"
|
||||
label={{ value: 'SLA 300ms', position: 'right', fill: 'var(--error)', fontSize: 9 }} />
|
||||
</ThemedChart>
|
||||
</Card>
|
||||
|
||||
<Card title="Errors by Route">
|
||||
<BarChart
|
||||
series={errorBarSeries}
|
||||
height={200}
|
||||
className={styles.chart}
|
||||
/>
|
||||
<Card title="Errors by Bucket">
|
||||
<ThemedChart data={chartData} height={200} xDataKey="idx" yLabel="errors">
|
||||
<Bar dataKey="errors" name="Errors" fill={CHART_COLORS[1]} />
|
||||
</ThemedChart>
|
||||
</Card>
|
||||
|
||||
<Card title="Message Volume (msg/min)">
|
||||
<AreaChart
|
||||
series={volumeChartSeries}
|
||||
yLabel="msg/min"
|
||||
height={200}
|
||||
className={styles.chart}
|
||||
/>
|
||||
<ThemedChart data={chartData} height={200} xDataKey="idx" yLabel="msg/min">
|
||||
<Area dataKey="volume" name="Volume" stroke={CHART_COLORS[0]}
|
||||
fill={CHART_COLORS[0]} fillOpacity={0.1} strokeWidth={2} dot={false} />
|
||||
</ThemedChart>
|
||||
</Card>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user