From 2cb88a4f5ec5f396a8c5cbd06c060320ff42cb53 Mon Sep 17 00:00:00 2001 From: wood chen Date: Sun, 9 Mar 2025 11:33:47 +0800 Subject: [PATCH] =?UTF-8?q?fix(metrics):=20=E4=BC=98=E5=8C=96=E5=BB=B6?= =?UTF-8?q?=E8=BF=9F=E7=BB=9F=E8=AE=A1=E5=92=8C=E5=88=86=E5=B8=83=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复延迟统计分布数据获取逻辑,增加更健壮的类型转换 - 确保延迟分布桶始终存在,即使没有数据 - 在处理器中为空分布数据添加默认初始化 - 优化指标收集器中的延迟桶初始化和数据获取方法 --- internal/handler/metrics.go | 27 ++++++++++++++++++++++----- internal/metrics/collector.go | 29 ++++++++++++++++++----------- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/internal/handler/metrics.go b/internal/handler/metrics.go index cdffe9b..ea58e49 100644 --- a/internal/handler/metrics.go +++ b/internal/handler/metrics.go @@ -161,15 +161,32 @@ func (h *ProxyHandler) MetricsHandler(w http.ResponseWriter, r *http.Request) { metrics.LatencyStats.Max = utils.SafeString(latencyStats["max"], "0ms") // 处理分布数据 - if distribution, ok := latencyStats["distribution"].(map[string]interface{}); ok { - metrics.LatencyStats.Distribution = make(map[string]int64) - for k, v := range distribution { - if intValue, ok := v.(float64); ok { - metrics.LatencyStats.Distribution[k] = int64(intValue) + if stats["latency_stats"] != nil { + if distribution, ok := stats["latency_stats"].(map[string]interface{})["distribution"]; ok && distribution != nil { + if distributionMap, ok := distribution.(map[string]interface{}); ok { + metrics.LatencyStats.Distribution = make(map[string]int64) + for k, v := range distributionMap { + if intValue, ok := v.(float64); ok { + metrics.LatencyStats.Distribution[k] = int64(intValue) + } else if intValue, ok := v.(int64); ok { + metrics.LatencyStats.Distribution[k] = intValue + } + } } } } + // 如果分布数据为空,初始化一个空的分布 + if metrics.LatencyStats.Distribution == nil { + metrics.LatencyStats.Distribution = make(map[string]int64) + // 添加默认的延迟桶 + metrics.LatencyStats.Distribution["<10ms"] = 0 + metrics.LatencyStats.Distribution["10-50ms"] = 0 + metrics.LatencyStats.Distribution["50-200ms"] = 0 + metrics.LatencyStats.Distribution["200-1000ms"] = 0 + metrics.LatencyStats.Distribution[">1s"] = 0 + } + // 填充错误统计数据 metrics.ErrorStats.ClientErrors = clientErrors metrics.ErrorStats.ServerErrors = serverErrors diff --git a/internal/metrics/collector.go b/internal/metrics/collector.go index 27fcf10..5efa491 100644 --- a/internal/metrics/collector.go +++ b/internal/metrics/collector.go @@ -61,11 +61,12 @@ func InitCollector(cfg *config.Config) error { instance.bandwidthStats.history = make(map[string]int64) // 初始化延迟分布桶 - instance.latencyBuckets.Store("<10ms", new(int64)) - instance.latencyBuckets.Store("10-50ms", new(int64)) - instance.latencyBuckets.Store("50-200ms", new(int64)) - instance.latencyBuckets.Store("200-1000ms", new(int64)) - instance.latencyBuckets.Store(">1s", new(int64)) + buckets := []string{"<10ms", "10-50ms", "50-200ms", "200-1000ms", ">1s"} + for _, bucket := range buckets { + counter := new(int64) + *counter = 0 + instance.latencyBuckets.Store(bucket, counter) + } // 启动数据一致性检查器 instance.startConsistencyChecker() @@ -344,14 +345,20 @@ func (c *Collector) GetStats() map[string]interface{} { // 收集延迟分布 latencyDistribution := make(map[string]int64) - c.latencyBuckets.Range(func(key, value interface{}) bool { - if counter, ok := value.(*int64); ok { - latencyDistribution[key.(string)] = atomic.LoadInt64(counter) + + // 确保所有桶都存在,即使计数为0 + buckets := []string{"<10ms", "10-50ms", "50-200ms", "200-1000ms", ">1s"} + for _, bucket := range buckets { + if counter, ok := c.latencyBuckets.Load(bucket); ok { + if counter != nil { + latencyDistribution[bucket] = atomic.LoadInt64(counter.(*int64)) + } else { + latencyDistribution[bucket] = 0 + } } else { - latencyDistribution[key.(string)] = value.(int64) + latencyDistribution[bucket] = 0 } - return true - }) + } // 获取最近请求记录(使用读锁) recentRequests := c.recentRequests.GetAll()