From 1123eb4107d7ea199ce615bd7e87825d2a8cde60 Mon Sep 17 00:00:00 2001 From: OG T Date: Thu, 2 Apr 2026 13:03:20 +0800 Subject: [PATCH] =?UTF-8?q?feat(web):=20Metrics=20Strip=20=E8=87=AA?= =?UTF-8?q?=E5=8B=95=E8=99=95=E7=BD=AE=E7=8E=87=20+=20MTTR=20=E7=9C=9F?= =?UTF-8?q?=E5=AF=A6=E8=A8=88=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - autoRemediationRate: resolved+closed / total incidents - mttrAvg: 平均 (updated_at - created_at) 分鐘/小時 - 替換原本的 '--' 靜態值 Co-Authored-By: Claude Opus 4.6 (1M context) --- apps/web/src/app/[locale]/page.tsx | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/apps/web/src/app/[locale]/page.tsx b/apps/web/src/app/[locale]/page.tsx index a3f12afa..bb48daca 100644 --- a/apps/web/src/app/[locale]/page.tsx +++ b/apps/web/src/app/[locale]/page.tsx @@ -43,6 +43,26 @@ export default function Home({ params }: { params: { locale: string } }) { enablePolling: true, }) + // Metrics Strip 計算 + const autoRemediationRate = (() => { + if (!incidents || incidents.length === 0) return '--' + const resolved = incidents.filter(i => i.status === 'resolved' || i.status === 'closed').length + if (resolved === 0) return '0%' + return `${((resolved / incidents.length) * 100).toFixed(0)}%` + })() + + const mttrAvg = (() => { + if (!incidents || incidents.length === 0) return '--' + const resolved = incidents.filter(i => i.updated_at && (i.status === 'resolved' || i.status === 'closed')) + if (resolved.length === 0) return '--' + const avgMs = resolved.reduce((sum, i) => { + return sum + (new Date(i.updated_at).getTime() - new Date(i.created_at).getTime()) + }, 0) / resolved.length + const mins = Math.round(avgMs / 60000) + if (mins < 60) return `${mins}m` + return `${(mins / 60).toFixed(1)}h` + })() + return (
i.severity === 'P0').length ? `+${incidents.filter((i) => i.severity === 'P0').length} P0` : tDashboard('stable') }, { label: tDashboard('serviceHealth'), value: `${pulseMetrics?.length ?? '--'}/${pulseMetrics?.length ?? '--'}`, sub: tDashboard('normal') }, { label: tDashboard('todayIncidents'), value: incidents?.length ?? '--', sub: '' }, - { label: tDashboard('autoRemediationRate'), value: '--', sub: '' }, - { label: tDashboard('mttrAvg'), value: '--', sub: '' }, + { label: tDashboard('autoRemediationRate'), value: autoRemediationRate, sub: '' }, + { label: tDashboard('mttrAvg'), value: mttrAvg, sub: '' }, ].map((m, i, arr) => (