grafana 不直接集成 go 微服务,需通过 prometheus 采集暴露在 /metrics 的指标;确保 promhttp.handler() 正确注册、路径严格为 /metrics、服务监听 0.0.0.0、指标打点触发且类型匹配、prometheus 抓取成功、grafana 数据源指向 prometheus。

Grafana 不是直接“集成”到 Golang 微服务里的——它不连 Go 进程,只连 Prometheus。你真正要做的,是让 Go 服务把指标暴露出来,Prometheus 把它们存住,Grafana 再从 Prometheus 里读。
/metrics 接口返回空或 404
这是最常卡住的第一步。没这个接口,后面全白搭。
-
http.Handle("/metrics", promhttp.Handler())必须在http.ListenAndServe()之前调用;放错顺序会导致 handler 注册失败,返回 HTTP 200 但 body 为空 - 路径必须严格是
/metrics,不是/metrics/、/monitor/metrics或带前缀的路径;Prometheus默认只拉这个路径 - 如果用了中间件(如 JWT 鉴权、日志拦截器),得显式跳过
/metrics路径,否则抓取会返回401或超时 - 服务监听地址要是
0.0.0.0:8080,不是127.0.0.1:8080;Docker 或 Kubernetes 环境下,localhost对Prometheus来说是不可达的
Counter 和 Histogram 打点后查不到数据
指标注册了,但 PromQL 查 http_requests_total 或 http_request_duration_seconds_bucket 始终为空,大概率是打点逻辑没触发或类型用错。
-
Counter必须在实际请求路径里调用.Inc()或.Add(1);只注册不打点 = 零值静默 -
Histogram必须调用.Observe(duration.Seconds()),且初始化时传入明确的Buckets(比如[]float64{0.05, 0.1, 0.25, 0.5, 1, 2.5});漏掉Observe()或buckets为空,_bucket系列指标就不会生成 - 标签要用
.WithLabelValues("GET", "200"),别用.With(map[string]string{"method": "GET"});后者容易因 map key 顺序或拼写不一致导致 series 爆炸,Prometheus存不下也查不出 - 延迟打点推荐用
prometheus.NewTimer()包裹 handler,比手写start := time.Now(); defer更可靠
Grafana 面板空白,先看 Prometheus 的 Targets 页面
Grafana 是“最后一环”,它连的是 Prometheus,不是你的 Go 服务。面板空白,优先查 Prometheus 是否真拿到了数据。
- 登录
PrometheusWeb UI(通常是:9090/targets),确认 job 状态是UP,而不是DOWN或failed - 检查
scrape_configs中 target 地址是否填对:比如填了localhost:8080,但Prometheus在 Docker 容器里,localhost指的是容器自身,不是宿主机上的 Go 服务 -
Grafana数据源配置里,URL 填的是Prometheus地址(如@#@#@#@#@#@#@#@#@#@0或@#@#@#@#@#@#@#@#@#@1),不是 Go 服务地址 - 所有自定义指标(
prometheus.NewCounter、prometheus.NewHistogramVec等)必须用prometheus.MustRegister()或显式Register(),否则不会出现在/metrics输出里
PromQL 查询延迟指标总报错或结果异常
直方图类指标(比如 http_request_duration_seconds)不能直接画图,必须用聚合函数 + 分位数计算,否则查不到或结果失真。
- 正确写法是:
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) - 错误写法:
http_request_duration_seconds(无意义,该指标本身不存在)或rate(http_request_duration_seconds_sum[5m]) / rate(http_request_duration_seconds_count[5m])(算术平均,不代表 P95) -
rate()必须作用于_bucket序列,不能作用于_sum或_count单独使用;否则分位数计算会失效 - 如果 Buckets 设置太宽(比如只有
[1, 5, 10]),P99 就会严重低估;生产环境建议至少覆盖 50ms–2s,按业务响应要求细化
真正容易被忽略的,是指标生命周期和网络拓扑的一致性:Go 服务暴露的地址、Prometheus 抓取时解析的 DNS、Grafana 连接 Prometheus 的网络路径,这三者必须在同一可达域内。跨 Docker network、K8s namespace、防火墙策略时,一个 curl -v @#@#@#@#@#@#@#@#@#@2 在 Prometheus 容器里跑不通,就什么都别指望了。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











