fix(api): handle zero-baseline edge cases in trend calculation

Introduce `CalculateTrendFloatWithBaseline` to correctly handle scenarios where previous period metrics (Error Rate, Latency) are zero or missing. This prevents arithmetic errors and distinguishes between "new" data and actual increases ("up") when starting from zero.

Also updates the admin panel dashboard documentation to reflect current project status.
This commit is contained in:
zenfun
2026-01-02 23:17:55 +08:00
parent 481f616704
commit 5c01497ce0
3 changed files with 114 additions and 7 deletions

View File

@@ -89,6 +89,31 @@ func CalculateTrendFloat(current, previous float64) TrendInfo {
return TrendInfo{Delta: &delta, Direction: direction}
}
// CalculateTrendFloatWithBaseline calculates trend when baseline existence is explicit.
func CalculateTrendFloatWithBaseline(current, previous float64, hasBaseline bool) TrendInfo {
if !hasBaseline {
if current == 0 {
return TrendInfo{Direction: "stable"}
}
return TrendInfo{Direction: "new"}
}
if previous == 0 {
if current == 0 {
return TrendInfo{Direction: "stable"}
}
return TrendInfo{Direction: "up"}
}
delta := (current - previous) / previous * 100
delta = math.Round(delta*10) / 10
direction := "stable"
if delta > 0.5 {
direction = "up"
} else if delta < -0.5 {
direction = "down"
}
return TrendInfo{Delta: &delta, Direction: direction}
}
// RequestStats contains request-related statistics
type RequestStats struct {
Total int64 `json:"total"`
@@ -302,20 +327,21 @@ func (h *DashboardHandler) GetSummary(c *gin.Context) {
if !prevStart.IsZero() && !prevEnd.IsZero() {
prevStats, err := h.aggregateFromLogRecords(prevStart, prevEnd)
if err == nil {
hasBaseline := prevStats.Requests > 0
prevErrorRate := 0.0
if prevStats.Requests > 0 {
if hasBaseline {
prevErrorRate = float64(prevStats.Failed) / float64(prevStats.Requests)
}
prevAvgLatency := 0.0
if prevStats.Requests > 0 {
if hasBaseline {
prevAvgLatency = float64(prevStats.LatencySumMs) / float64(prevStats.Requests)
}
trends = &DashboardTrends{
Requests: CalculateTrend(totalRequests, prevStats.Requests),
Tokens: CalculateTrend(ts.TokensIn+ts.TokensOut, prevStats.TokensIn+prevStats.TokensOut),
ErrorRate: CalculateTrendFloat(errorRate, prevErrorRate),
Latency: CalculateTrendFloat(ts.AvgLatency, prevAvgLatency),
ErrorRate: CalculateTrendFloatWithBaseline(errorRate, prevErrorRate, hasBaseline),
Latency: CalculateTrendFloatWithBaseline(ts.AvgLatency, prevAvgLatency, hasBaseline),
}
}
}