feat(metrics): Improve latency tracking and error visualization

- Add atomic operations to track minimum and maximum request latency
- Update GetStats method to handle uninitialized latency values
- Modify dashboard error chart with improved color scheme and legend
- Adjust chart margins and axis width for better readability
This commit is contained in:
wood chen 2025-02-15 18:24:55 +08:00
parent 35ea14a91f
commit d00ab0a6e1
2 changed files with 35 additions and 6 deletions

View File

@ -88,6 +88,27 @@ func (c *Collector) RecordRequest(path string, status int, latency time.Duration
atomic.AddInt64(&c.totalBytes, bytes)
atomic.AddInt64(&c.latencySum, int64(latency))
// 更新最小和最大响应时间
latencyNanos := int64(latency)
for {
oldMin := atomic.LoadInt64(&c.minLatency)
if oldMin <= latencyNanos {
break
}
if atomic.CompareAndSwapInt64(&c.minLatency, oldMin, latencyNanos) {
break
}
}
for {
oldMax := atomic.LoadInt64(&c.maxLatency)
if oldMax >= latencyNanos {
break
}
if atomic.CompareAndSwapInt64(&c.maxLatency, oldMax, latencyNanos) {
break
}
}
// 更新延迟分布
latencyMs := latency.Milliseconds()
var bucketKey string
@ -245,6 +266,13 @@ func (c *Collector) GetStats() map[string]interface{} {
}
}
// 获取最小和最大响应时间
minLatency := atomic.LoadInt64(&c.minLatency)
maxLatency := atomic.LoadInt64(&c.maxLatency)
if minLatency == math.MaxInt64 {
minLatency = 0
}
return map[string]interface{}{
"uptime": time.Since(c.startTime).String(),
"active_requests": atomic.LoadInt64(&c.activeRequests),
@ -258,8 +286,8 @@ func (c *Collector) GetStats() map[string]interface{} {
"top_paths": pathMetrics,
"recent_requests": c.recentRequests,
"latency_stats": map[string]interface{}{
"min": fmt.Sprintf("%.2fms", float64(atomic.LoadInt64(&c.minLatency))/float64(time.Millisecond)),
"max": fmt.Sprintf("%.2fms", float64(atomic.LoadInt64(&c.maxLatency))/float64(time.Millisecond)),
"min": fmt.Sprintf("%.2fms", float64(minLatency)/float64(time.Millisecond)),
"max": fmt.Sprintf("%.2fms", float64(maxLatency)/float64(time.Millisecond)),
"distribution": latencyDistribution,
},
"error_stats": map[string]interface{}{

View File

@ -61,7 +61,7 @@ interface Metrics {
}
// 颜色常量
const COLORS = ['#0088FE', '#00C49F', '#FFBB28', '#FF8042', '#8884d8']
const COLORS = ['#0088FE', '#FF8042', '#00C49F', '#FFBB28', '#FF0000']
export default function DashboardPage() {
const [metrics, setMetrics] = useState<Metrics | null>(null)
@ -395,13 +395,14 @@ export default function DashboardPage() {
value,
}))}
layout="vertical"
margin={{ top: 5, right: 30, left: 100, bottom: 5 }}
margin={{ top: 5, right: 30, left: 120, bottom: 5 }}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis type="number" />
<YAxis type="category" dataKey="name" />
<YAxis type="category" dataKey="name" width={120} />
<Tooltip />
<Bar dataKey="value" fill="#FF8042" />
<Legend />
<Bar dataKey="value" name="错误次数" fill={COLORS[1]} />
</BarChart>
</ResponsiveContainer>
</div>