go服务暴露/metrics端点需三步:显式注册指标(如mustregister(newgocollector()))、挂载promhttp.handler()到/metrics、监听0.0.0.0;缺一则prometheus抓取失败或grafana无数据。

Go 服务暴露的 /metrics 端点能被 Prometheus 正常抓取,且 Grafana 能查到数据并画出曲线——这三者连通才算真正跑通。否则只是“看起来配好了”,实际告警和图表全是空的。
Go 服务里 /metrics 返回空或 404
根本原因不是路由没写,而是指标没注册进默认注册表,或者 HTTP handler 被中间件拦截了。
-
prometheus.MustRegister()必须在init()或main()开头调用,不能放在 handler 函数里——否则每次请求都尝试注册,触发duplicate metrics collector registration attemptedpanic - 用
promauto.NewCounter会自动注册,适合快速验证;但自定义指标(比如带 label 的NewCounterVec)必须显式MustRegister - Gin/echo 等框架中,
/metrics路由要加r.GET("/metrics", promhttp.Handler()),且确保没被 auth、cors 中间件拦截——可临时加r.Use(func(c echo.Context) error { return c.Next() })排查 - 启动后手动
curl http://localhost:8080/metrics,应看到类似go_goroutines 12的原生指标;若为空,说明注册失败;若返回 404,说明路由未生效
Prometheus targets 页面显示 DOWN
这不是配置写错了,而是网络、协议或超时层面卡住了。常见于 Docker/K8s 环境。
- Go 服务监听地址必须是
0.0.0.0:8080,不能是127.0.0.1:8080——后者在容器里只绑本地回环,Prometheus 容器无法访问 -
scrape_timeout默认 10s,但若/metricshandler 里做了同步 DB 查询或外部 HTTP 调用,极易超时;建议先设为5s并检查 Prometheus 日志是否出现context deadline exceeded - K8s 场景下 targets 地址别写 Pod IP(会变),改用 Service DNS:
my-service.default.svc.cluster.local:8080;若用 Ingress 暴露/metrics,需确认 Ingress controller 支持 HTTP/1.1 且未禁用Transfer-Encoding: chunked
Grafana 查不到 rate(http_requests_total[5m]) 数据
不是 PromQL 写错,而是指标类型或标签不匹配导致聚合失败。
-
rate()只能用于Counter类型,对Gauge(如内存使用量)要用delta()或直接画原始值 - 确保
http_requests_total真正有打点:handler 里必须调用counter.WithLabelValues("GET", "/api/user", "200").Inc(),否则时间序列压根不存在 - label 名称必须完全一致:
method和Method是两个不同维度;PromQL 中rate(http_requests_total{method="GET"}[5m])若无结果,先查http_requests_total是否有该 label 键 - 如果用了自定义注册表(非默认),
promhttp.HandlerFor(registry, ...)必须传入同一 registry,否则 Prometheus 抓的是空注册表
最易被忽略的一点:Prometheus 抓取间隔(scrape_interval)和 Grafana 查询时间范围不匹配。比如设了 scrape_interval: 30s,却在 Grafana 里查过去 10 秒的数据,必然为空——得等至少一个完整周期才有第一个点。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











