Go服务/metrics为空因指标未注册,默认注册表为空;须显式调用MustRegister(NewGoCollector())及自定义指标,且不可在handler中重复注册;Counter不显示常因label不匹配或未调用Inc();Prometheus target为DOWN多因网络配置错误,如监听地址应为:9091而非127.0.0.1:9091。

Go 服务暴露 /metrics 端点为什么返回空?
不是 handler 没挂上,是指标根本没注册进默认注册表。promhttp.Handler() 只吐已注册的指标,而默认只带空注册表——运行时指标(如 go_goroutines)也不会自动出现。
- 必须显式调用
prometheus.MustRegister(prometheus.NewGoCollector()),通常放在init()或main()开头 - 自定义指标(如
http_requests_total)也要在同一阶段注册,不能等到第一个请求才创建+注册,否则首次抓取永远为空 - 别在 HTTP handler 里反复调用
NewCounter()+MustRegister(),会 panic 报 “duplicate metrics collector registration attempted” - 如果用了
prometheus.NewRegistry()自定义注册表,就得用promhttp.HandlerFor(reg, ...),否则promhttp.Handler()仍查默认表,你的指标看不见
Counter 在 /metrics 里始终不显示?检查 label 和调用链
Counter 默认不输出零值,这是设计行为,不是 bug。但更常见的“不显示”其实是 label 不匹配或调用遗漏。
-
NewCounterVec(..., []string{"method", "status"})定义了两个 label,调用时就必须传两个非空字符串:.WithLabelValues("GET", "200").Inc();传"GET", ""或少传一个,会 panic - label 名称大小写和顺序必须完全一致:定义是
status,就不能在WithLabelValues里传"statusCode",指标虽存但 Prometheus 查询不到 - 确保业务 handler 真的执行到了
.Inc()或.Add()——比如中间件提前 return、panic、或路由没匹配上,计数器就永远不会被触发 - 用
curl -s http://localhost:9091/metrics | grep http_requests_total直接验证,避免被 Grafana 缓存或查询语法误导
Prometheus targets 显示 DOWN?先盯住网络和监听地址
90% 的 DOWN 状态和 Go 代码无关,而是网络层或配置错位。Prometheus 日志里若出现 server returned HTTP status 404 Not Found 或 context deadline exceeded,基本可排除指标逻辑问题。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- Go 服务监听地址别写
127.0.0.1:9091,要写:9091(即绑定""),否则容器外、宿主机或 Kubernetes Service 无法访问 -
scrape_configs.targets别填localhost:9091——这是 Prometheus 自己的 localhost,不是你 Go 服务的;Docker Desktop 用host.docker.internal:9091,K8s 用 Service DNS 名如my-service.default.svc.cluster.local:9091 - 确认防火墙/安全组放行了目标端口;
telnet your-go-app 9091能通,才是网络层 OK - scrape timeout 默认 10s,若
/metrics响应慢(比如同步读 DB),先临时设成scrape_timeout: 5s并观察日志
报警规则 for: 2m 一直不 firing?注意 scrape_interval 和评估频率
for: 2m 不是“持续两分钟”,而是“连续满足条件的评估次数 ≥ ceil(2m / scrape_interval)”。这个细节被大量忽略。
立即学习“go语言免费学习笔记(深入)”;
- 若
scrape_interval: 30s,则for: 2m要求连续 4 次抓取都满足条件才会触发;中间任何一次不满足,计数清零 - 规则中用
OFFSET(如http_requests_total OFFSET 5m)时,Prometheus 必须能回溯到 5 分钟前的数据——如果 retention 时间太短或历史数据被清理,表达式直接返回空,不会告警 -
rate()类函数对采样点敏感:若scrape_interval太大(如 2m),rate(http_requests_total[5m])可能因点太少而计算失败;建议保持scrape_interval ≤ 30s,range vector至少覆盖 4×interval - 在 Prometheus 表达式浏览器里直接输入规则表达式(如
http_requests_total{job="my-service"} ),看是否真有数据返回,再加 <code>FOR和OFFSET

















