gin服务暴露/metrics端点必须用gin.wraph(promhttp.handler())包装,否则因content-type协商失败导致406或空响应;自定义指标需包级定义、启动时注册且打点复用,计数器不可用于活跃连接统计。

Gin 框架本身不对接 Grafana,真正起作用的是你暴露的 /metrics 接口是否被 Prometheus 正确抓取——Grafana 只是最后一步的“画图工具”。90% 的面板空白问题,根源不在 Grafana 配置,而在 Gin 服务没把指标真正交出去。
为什么 router.GET("/metrics", ...) 会失败
Gin 的 GET 方法注册的是 HTTP handler,但 promhttp.Handler() 是标准库 http.Handler 类型,它依赖 Content-Type 自协商和流式响应机制,直接塞进 Gin 路由会丢失关键 header 处理逻辑。
- 必须用
gin.WrapH(promhttp.Handler())包一层,而不是router.GET("/metrics", func(c *gin.Context) { ... }) - 别在中间件里对
/metrics做鉴权或日志拦截——Prometheus 抓取是无状态、无 token 的请求,401/403 直接导致 targets 显示 DOWN - 如果用了
gin.BasicAuth或 JWT 中间件,得显式跳过该路径:router.NoRoute(...)不够,要提前router.Use(...)之外单独挂载
curl http://localhost:8080/metrics 返回空或 404 怎么查
先确认端点是否存在且可访问,这是所有后续步骤的前提。空响应比 404 更危险——说明 handler 注册了但没数据。
- 检查
http.Handle("/metrics", promhttp.Handler())是否在router.Run()之前调用;Gin 场景下等价于router.Any("/metrics", gin.WrapH(promhttp.Handler()))是否最先注册 - 运行时执行
curl -v http://localhost:8080/metrics,看返回Content-Type: text/plain; version=0.0.4; charset=utf-8——不是application/json或text/html - 搜索响应体里是否有
go_goroutines:没有说明 runtime 指标没注册,加一行prometheus.MustRegister(prometheus.NewGoCollector())(v1.14 以下必须) - Docker 环境下别 curl
localhost,改用宿主机 IP 或host.docker.internal(Mac/Win),Linux 用172.17.0.1
Grafana 查不到自定义指标比如 http_requests_total
指标名存在但值为 0 或无数据,大概率是打点位置错了,或者 Vec 实例没复用。
- 计数器必须在业务 handler 内调用
.Inc()或.WithLabelValues("GET", "200").Inc(),不能只定义不调用 - 用
prometheus.NewCounterVec时,var reqTotal = prometheus.NewCounterVec(...)必须是包级变量,init()里MustRegister(reqTotal),否则每次请求都新建实例,Prometheus 存储爆炸且 label 不一致 - 延迟直方图打点要用
defer包裹:start := time.Now(); defer func(){ hist.Observe(time.Since(start).Seconds()) }(),漏 defer 就永远不打点 - 验证是否真打了:重启服务后发几次请求,再
curl /metrics | grep http_requests_total,看数值是否递增
Prometheus targets 显示 UP 但 Grafana 面板还是空
这说明数据已进 Prometheus,但查询语句或时间范围不匹配。
- 在 Grafana 的 Explore 页面,选 Prometheus 数据源,直接输入
http_requests_total看有没有 raw series;没有就说明 label 键名拼错(比如用了"status_code"但打点用的是"status") - 查 QPS 别直接看
http_requests_total,要用rate(http_requests_total[5m]);查 P95 延迟别漏rate():正确写法是histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) - Grafana 时间范围选 “Last 5 minutes”,别用 “Today”——刚启动的服务可能还没积累足够 scrape 数据点
- 确认 Prometheus 的
scrape_interval(默认 15s)和 Grafana 刷新间隔(默认 30s)没冲突;太短的 interval 可能导致重复采样或抓不到最新点
最常被忽略的一点:Gin 服务监听地址写的是 127.0.0.1:8080,而 Prometheus 容器根本连不到这个地址——必须是 0.0.0.0:8080,且 Kubernetes Service 或 Docker network 要确保该端口对外暴露。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











