/metrics 返回空或404是因为指标未注册或未暴露;Kratos不自动开启metrics采集,需手动调用srv.Handle("/metrics", promhttp.Handler())挂载端点,并确保meter创建后显式上报、registry一致且正确传入handler。

/metrics 返回空或 404,说明指标根本没注册或没暴露。Kratos 不会自动开启 metrics 采集,也不默认挂载 /metrics 端点——这是最常被忽略的前提。
kratos 中没调用 srv.Handle("/metrics", promhttp.Handler())
即使你创建了所有指标,只要没把 handler 挂到 HTTP Server 上,curl localhost:8000/metrics 就只会返回 404 或空响应。
- 必须在
http.NewServer构建后、server.Start()前调用srv.Handle("/metrics", promhttp.Handler()) - 不要把它塞进中间件链(比如
http.WithMiddleware),/metrics不需要鉴权、trace 或日志,绕过中间件更安全 - 确认路径是
/metrics,不是/actuator/metrics或/prometheus——后者会导致 Prometheus 抓取时返回 404
指标创建了但没上报,/metrics 里看不到数据
Kratos 的 metrics.DefaultMeter 只提供接口,不自动埋点。你不显式调用 .Add() 或 .Record(),指标就永远静默。
- 计数器用
meters.NewCounter,创建后必须在业务逻辑中调用counter.Add(1)才会出现在/metrics输出里 - 直方图用
meters.NewHistogram,推荐用于耗时统计,但bucket设置要贴近真实分布(比如 P95 在 200ms,就别只设到 100ms) - 所有
meters.NewXXX调用应放在init()或 service 初始化阶段,避免在请求 hot path 上反复创建——这会严重拖慢性能且导致指标名重复
registry 没传给 promhttp.Handler(),指标注册了也白搭
默认的 promhttp.Handler() 使用全局 registry,但如果你手动调用了 prometheus.NewRegistry() 却没把它传进去,指标就只注册在新 registry 里,而 handler 还在读默认 registry,自然为空。
- 若需自定义 registry,必须显式传入:
promhttp.HandlerFor(registry, promhttp.HandlerOpts{}) - 检查是否误用了
prometheus.MustRegister()——它只作用于默认 registry,和你新建的 registry 无关 - 确保
metrics.DefaultMeter底层绑定的是你最终传给 handler 的那个 registry(Kratos 默认用prometheus.DefaultRegisterer,即全局 registry)
最容易被忽略的一点:Kratos 的 metrics 是“被动暴露”,没有自动扫描、没有魔法注入、也没有默认指标。从 registry 初始化、handler 挂载、meter 创建、到每次上报,每一步都得你亲手写代码触发——少任何一环,/metrics 就是空的。











