counter用于请求计数以支持rate()计算变化率,histogram用于延迟分布统计以支持p95、avg等分析;gauge无法满足red指标对聚合统计和分布特征的要求。

为什么用 Counter + Histogram 而不是 Gauge 记请求和延迟
RED 指标(Rate、Errors、Duration)本质是聚合统计,不是瞬时快照。用 Gauge 记请求数会导致 rate() 查询始终为 0 或负值——因为 rate() 只对单调递增的 Counter 有意义;用 Gauge 记延迟则完全失去分布信息,无法算 p95、avg 或分桶占比。
正确做法:
-
http_requests_total必须是CounterVec,带method和status标签,每次请求.Inc() -
http_request_duration_seconds必须是HistogramVec,Buckets 要贴合实际延迟分布(比如[]float64{0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10}),不能直接用DefBuckets - 错误数不要单独建指标,而是从
http_requests_total{status=~"5..|4.."}这类 label 过滤得出,避免指标爆炸
注册指标时 panic: "duplicate metrics collector registration attempted"
这个错误几乎都来自重复调用 prometheus.MustRegister(),尤其在热重载、测试多 goroutine 并发初始化、或误在 handler 里注册指标时发生。
规避方式:
- 所有
MustRegister()放在init()函数或main()开头,且只执行一次 - 改用
promauto.NewCounterVec替代prometheus.NewCounterVec+MustRegister,它内部自动处理注册逻辑,线程安全,且支持懒注册 - 如果必须动态注册(如插件式模块),先用
prometheus.Unregister()清理旧实例,再注册新实例
/metrics 端点返回空或 404
最常见原因是用了已弃用的 prometheus.Handler(),或者 HTTP 路由没挂对 handler。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
检查点:
- 必须用
promhttp.Handler(),不能写成http.Handle("/metrics", prometheus.Handler())—— 后者在 v1.0+ 已移除 - 确保
http.Handle("/metrics", promhttp.Handler())在http.ListenAndServe()前执行 - 若用 Gin/Fiber 等框架,别漏掉中间件注册:Gin 中要写
r.GET("/metrics", gin.WrapH(promhttp.Handler())) - 访问
curl http://localhost:8080/metrics时,确认服务已启动且端口未被占用
延迟直方图的 _bucket 标签太多导致 Prometheus 存储膨胀
Histogram 每个 Bucket 都生成一条时间序列,11 个 bucket × 10 个 path × 5 个 method = 550 条序列。标签组合爆炸是高频踩坑点。
压缩策略:
- 精简标签:去掉低区分度 label,比如不用
path而用route(如"user_create"),或聚合到一级路径"/user/*" - 减少 bucket 数量:生产环境 8~10 个 bucket 足够,避免
[]float64{0.001, 0.002, ..., 10}这种密度过高的设置 - 慎用
Summary:它在客户端计算分位数,不支持 Prometheus 多实例聚合,RED 场景下基本无用
真正难的不是写几行注册代码,而是想清楚哪些 label 真正影响排查效率,哪些只是让存储账单变厚。指标设计一旦上线,改 label 名或删 bucket 都要同步改所有 PromQL 查询和 Grafana 面板——这点容易被忽略。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










