From 318aa5e0d37c0d4f0ef7d09f241042d30cf461b1 Mon Sep 17 00:00:00 2001 From: shaw Date: Mon, 30 Mar 2026 21:43:07 +0800 Subject: [PATCH] feat: add cache hit rate line to token usage trend chart Add a purple dashed line showing cache hit rate percentage (cache_read / (cache_read + cache_creation)) on a secondary right Y-axis (0-100%). Applies to both user and admin dashboards. --- .../src/components/charts/TokenUsageTrend.vue | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/charts/TokenUsageTrend.vue b/frontend/src/components/charts/TokenUsageTrend.vue index a255fb03..4cd126b9 100644 --- a/frontend/src/components/charts/TokenUsageTrend.vue +++ b/frontend/src/components/charts/TokenUsageTrend.vue @@ -64,7 +64,8 @@ const chartColors = computed(() => ({ input: '#3b82f6', output: '#10b981', cacheCreation: '#f59e0b', - cacheRead: '#06b6d4' + cacheRead: '#06b6d4', + cacheHitRate: '#8b5cf6' })) const chartData = computed(() => { @@ -104,6 +105,19 @@ const chartData = computed(() => { backgroundColor: `${chartColors.value.cacheRead}20`, fill: true, tension: 0.3 + }, + { + label: 'Cache Hit Rate', + data: props.trendData.map((d) => { + const total = d.cache_read_tokens + d.cache_creation_tokens + return total > 0 ? (d.cache_read_tokens / total) * 100 : 0 + }), + borderColor: chartColors.value.cacheHitRate, + backgroundColor: `${chartColors.value.cacheHitRate}20`, + borderDash: [5, 5], + fill: false, + tension: 0.3, + yAxisID: 'yPercent' } ] } @@ -132,6 +146,9 @@ const lineOptions = computed(() => ({ tooltip: { callbacks: { label: (context: any) => { + if (context.dataset.yAxisID === 'yPercent') { + return `${context.dataset.label}: ${context.raw.toFixed(1)}%` + } return `${context.dataset.label}: ${formatTokens(context.raw)}` }, footer: (tooltipItems: any) => { @@ -168,6 +185,21 @@ const lineOptions = computed(() => ({ }, callback: (value: string | number) => formatTokens(Number(value)) } + }, + yPercent: { + position: 'right' as const, + min: 0, + max: 100, + grid: { + drawOnChartArea: false + }, + ticks: { + color: chartColors.value.cacheHitRate, + font: { + size: 10 + }, + callback: (value: string | number) => `${value}%` + } } } }))