不会panic,但未注册则/metrics中不可见;必须先用prometheus.mustregister()显式注册到defaultregisterer,否则指标不暴露,且重复注册同名指标才会panic。

直接加 prometheus.NewCounter 会 panic?先注册再用
Go 里直接 new 一个 prometheus.Counter 并不会自动暴露给 Prometheus server,更不会被 promhttp.Handler() 收集——它压根没注册进默认的 prometheus.DefaultRegisterer。常见错误是写完指标变量就调 Inc(),结果 metrics endpoint 里完全看不到这条指标,甚至程序启动时 panic 报 “duplicate metric registration”。
- 所有指标(
Counter、Gauge、Histogram)必须显式注册,推荐用prometheus.MustRegister() - 避免重复注册:同一名称+标签组合只能注册一次;若需动态构造指标,用
prometheus.NewXXXVec+WithLabelValues() - 别在函数内部反复 new 指标——指标实例应全局唯一,初始化时创建并注册一次即可
HTTP handler 里怎么埋点?用 http.HandlerFunc 包一层
最轻量的方式不是改原有 handler 函数体,而是套一层中间件。这样既不侵入业务逻辑,又能统一统计请求总量、延迟、状态码分布。
- 用
promhttp.InstrumentHandlerCounter和promhttp.InstrumentHandlerDuration最省事,它们自动提取method、code、route标签 - 如果用了 gorilla/mux 或 chi,注意
route标签值取决于你是否调用promhttp.WithRouteMatcher,否则默认是空字符串或"unknown" - 自定义标签(比如按用户角色分流统计)要自己写 wrapper:先
req.Context()取信息,再调yourCounterVec.WithLabelValues(role).Inc()
普通函数怎么加监控?靠 defer + ObserveDuration
非 HTTP 场景(比如定时任务、消息消费、DB 查询封装)加监控,核心是记录执行耗时和成功/失败次数。别手动算时间差,用 prometheus.NewHistogramVec 配合 ObserveDuration() 更可靠。
-
ObserveDuration()会自动调time.Since(start),精度高且不易出错 - 失败计数建议用
CounterVec,标签至少包含error_type(比如"timeout"、"db_conn_failed"),别只用布尔值 - 避免在循环里高频调
Inc()—— 如果每秒上千次,考虑聚合后批量上报,或换用Summary(但注意 Summary 不支持多维标签)
本地验证指标有没有生效?curl /metrics 看原始文本
跑起来之后别急着打开 Grafana,先用最原始方式确认指标已注册且有数据:
- 启动服务后执行
curl http://localhost:8080/metrics | grep your_metric_name - 看到类似
your_api_request_duration_seconds_sum{code="200",method="GET",route="/api/user"} 12.45才算真正接入成功 - 如果指标名带下划线(如
http_request_duration_seconds),注意 Prometheus 表达式里不能用-,得写成http_request_duration_seconds而不是http-request-duration-seconds
指标命名和标签设计一旦上线就很难改,尤其当已有告警或 dashboard 依赖时。一开始多花两分钟想清楚 job、instance、service 这些基础标签要不要加,比后期修数据容易得多。











