refactor(ops): 使用TTFT替代Duration作为健康分数指标

- 业务健康分数:错误率 50% + TTFT 50%
- TTFT 阈值:1s → 100分,3s → 0分
- TTFT 对 AI 服务的用户体验更有意义
- 更新所有相关测试用例期望值
This commit is contained in:
IanShaw027
2026-01-14 23:47:43 +08:00
parent d5eab7da3b
commit a7a49be850
2 changed files with 19 additions and 19 deletions

View File

@@ -32,7 +32,7 @@ func computeDashboardHealthScore(now time.Time, overview *OpsDashboardOverview)
} }
// computeBusinessHealth calculates business health score (0-100) // computeBusinessHealth calculates business health score (0-100)
// Components: Error Rate (50%) + Latency (50%) // Components: Error Rate (50%) + TTFT (50%)
func computeBusinessHealth(overview *OpsDashboardOverview) float64 { func computeBusinessHealth(overview *OpsDashboardOverview) float64 {
// Error rate score: 1% → 100, 10% → 0 (linear) // Error rate score: 1% → 100, 10% → 0 (linear)
// Combines request errors and upstream errors // Combines request errors and upstream errors
@@ -48,22 +48,22 @@ func computeBusinessHealth(overview *OpsDashboardOverview) float64 {
} }
} }
// Latency score: 1s → 100, 2s → 0 (linear) // TTFT score: 1s → 100, 3s → 0 (linear)
// Uses P99 of duration // Time to first token is critical for user experience
latencyScore := 100.0 ttftScore := 100.0
if overview.Duration.P99 != nil { if overview.TTFT.P99 != nil {
p99 := float64(*overview.Duration.P99) p99 := float64(*overview.TTFT.P99)
if p99 > 1000 { if p99 > 1000 {
if p99 <= 2000 { if p99 <= 3000 {
latencyScore = (2000 - p99) / 1000 * 100 ttftScore = (3000 - p99) / 2000 * 100
} else { } else {
latencyScore = 0 ttftScore = 0
} }
} }
} }
// Weighted combination: 50% error rate + 50% latency // Weighted combination: 50% error rate + 50% TTFT
return errorScore*0.5 + latencyScore*0.5 return errorScore*0.5 + ttftScore*0.5
} }
// computeInfraHealth calculates infrastructure health score (0-100) // computeInfraHealth calculates infrastructure health score (0-100)

View File

@@ -127,8 +127,8 @@ func TestComputeDashboardHealthScore_Comprehensive(t *testing.T) {
MemoryUsagePercent: float64Ptr(75), MemoryUsagePercent: float64Ptr(75),
}, },
}, },
wantMin: 61, wantMin: 96,
wantMax: 62, wantMax: 97,
}, },
{ {
name: "DB failure", name: "DB failure",
@@ -203,8 +203,8 @@ func TestComputeDashboardHealthScore_Comprehensive(t *testing.T) {
MemoryUsagePercent: float64Ptr(30), MemoryUsagePercent: float64Ptr(30),
}, },
}, },
wantMin: 25, wantMin: 84,
wantMax: 50, wantMax: 85,
}, },
{ {
name: "combined failures - business healthy + infra degraded", name: "combined failures - business healthy + infra degraded",
@@ -303,15 +303,15 @@ func TestComputeBusinessHealth(t *testing.T) {
wantMax: 78, wantMax: 78,
}, },
{ {
name: "latency boundary 2s", name: "TTFT boundary 2s",
overview: &OpsDashboardOverview{ overview: &OpsDashboardOverview{
SLA: 0.99, SLA: 0.99,
ErrorRate: 0, ErrorRate: 0,
UpstreamErrorRate: 0, UpstreamErrorRate: 0,
Duration: OpsPercentiles{P99: intPtr(2000)}, TTFT: OpsPercentiles{P99: intPtr(2000)},
}, },
wantMin: 50, wantMin: 75,
wantMax: 50, wantMax: 75,
}, },
{ {
name: "upstream error dominates", name: "upstream error dominates",