必须手动挂载 promhttp.Handler,否则 /metrics 端点不会暴露;echo-contrib/prometheus 仅注册指标不暴露路由,需显式注册 e.GET("/metrics", echo.WrapHandler(promhttp.Handler())) 或 http.Handle("/metrics", promhttp.Handler())。

必须手动挂载 promhttp.Handler,否则 /metrics 端点不会暴露,Prometheus 抓取会直接失败(Targets 显示 DOWN)。
为什么 echo.New() 后加 p.Use(e) 不够用
echo-contrib/prometheus 提供的 prometheus.NewPrometheus 只负责注册基础指标(如 HTTP 请求计数、延迟直方图),它 不自动暴露 /metrics 路由。很多开发者误以为调用 p.Use(e) 就万事大吉,结果 Prometheus 去请求 http://localhost:1323/metrics 时返回 404。
根本原因:Echo 的中间件只拦截已定义的路由,而 /metrics 是一个独立 HTTP handler,需显式注册到 Go 的 http.ServeMux 或 Echo 的路由系统中。
- 正确做法是用
e.GET("/metrics", echo.WrapHandler(promhttp.Handler()))(推荐,走 Echo 路由链) - 或退一步用
http.Handle("/metrics", promhttp.Handler())+ 单独启 http server(绕过 Echo,但失去中间件能力) - 绝对不要写
http.HandleFunc("/metrics", promhttp.Handler().ServeHTTP)—— 这是 v0.x 旧写法,v1.0+ 已废弃,运行时报 panic
promhttp.HandlerFor 和默认注册器的关系
新版 client_golang(v1.15+)要求显式传入注册器。如果你没创建自定义注册器,就用 prometheus.DefaultRegisterer;如果用了 reg := prometheus.NewRegistry(),就必须把所有指标(包括 echo-contrib 注册的)都注册到它上面,再传给 promhttp.HandlerFor,否则 /metrics 返回空。
Echo框架 5.1.0 版本源码包下载,适合关注 RealIP 行为变化、StartConfig.Listener、NewDefaultFS 和观测性中间件入口的开发团队。
- echo-contrib 默认注册到
prometheus.DefaultRegisterer,所以最简写法是:http.Handle("/metrics", promhttp.HandlerFor(prometheus.DefaultRegisterer, promhttp.HandlerOpts{})) - 若用自定义注册器,需在初始化时补上:
p := prometheus.NewPrometheus("echo", nil)<br>p.SetRegisterer(reg) // 关键!否则指标不进 reg<br>p.Use(e) - 漏掉
SetRegisterer是常见坑,会导致 Targets 显示 UP,但查不到任何http_*指标
自定义指标和 label 的安全写法
想统计某个业务路径的调用量?别直接用请求路径做 label 值,比如 path="/user/123"——这会产生高基数,几十万用户就把 Prometheus 拖垮。
- 安全 label 示例:
route="GET /user/{id}"、env="prod"、service="auth-api" - 危险 label 示例:
user_id="123456"、request_id="req-abc"、path="/order/789" - 定义带 label 的指标时,
Name必须全小写+下划线,Help不能为空:prometheus.NewCounterVec(prometheus.CounterOpts{<br> Name: "myapp_user_login_total",<br> Help: "Total number of user login attempts",<br>}, []string{"status", "method"}) - 避免在 handler 里反复调用
WithLabelValues,建议提前缓存常用组合:loginSuccess := counterVec.WithLabelValues("success", "post")
验证端点是否生效的三步检查法
启动服务后别急着配 Prometheus,先本地 curl 一把,看输出是否符合 OpenMetrics 规范:
- 执行
curl -v http://localhost:1323/metrics,状态码必须是 200,Content-Type 必须含text/plain; version=0.0.4 - 响应体里要有至少一行
# HELP和对应# TYPE,例如:# HELP echo_http_request_duration_seconds HTTP request duration in seconds<br># TYPE echo_http_request_duration_seconds histogram
- 不能出现
http: superfluous response.WriteHeader call日志——这说明某个中间件或 handler 手动写了 header 又调了http.Error,会破坏 metrics 响应格式
label 值为空、指标缺失、Targets 显示 context deadline exceeded,八成出在这三步里的某一处。真正麻烦的不是写代码,而是确认指标从 Go 进程里“干净地流出来”。

















