Kratos 接入监控指标需区分应用与基础设施指标,metrics 默认不自动暴露 /metrics 端点,须手动注册;自定义业务指标应使用 OpenTelemetry SDK 并统一 resource 属性确保可聚合与链路关联。

kratos 框架默认已集成 OpenTelemetry,但「接入监控指标」不是开个中间件就完事——它需要明确区分「应用指标」和「基础设施指标」,且两者采集路径、数据格式、后端接收方式完全不同。直接启用 tracing 中间件只解决链路追踪,对 Metrics(如请求 QPS、延迟直方图、错误率)没用。
kratos 的 metrics 默认不自动上报 Prometheus
kratos 提供了 metrics 接口抽象,默认实现是 prometheus 注册器,但它只是把指标注册到 prometheus.DefaultRegisterer,**不会自动暴露 HTTP 端点或定时上报**。常见错误是以为加了 metrics.NewPrometheus 就能被 Prometheus 抓取,结果 curl :9091/metrics 404。
- 必须手动注册
/metrics路由:用http.Handle("/metrics", promhttp.Handler())(注意不是promhttp.HandlerFor,避免重复注册) - 确保服务监听端口(如
:9091)对外可访问,K8s Service 需开放该端口并加prometheus.io/scrape: "true"annotation - 不要在多个 goroutine 里并发调用
prometheus.MustRegister,会 panic;统一在init()或main()开头注册 -
kratos的transport.HTTP和transport.GRPC中间件自带指标打点(如http_server_request_duration_seconds),但需显式传入metrics.Server实例,否则打点函数为空操作
OpenTelemetry Collector 是指标聚合的关键跳板
如果你的部署环境是 Kubernetes,别直接让每个 kratos 服务暴露 /metrics 给 Prometheus 抓——这会造成大量 scrape 连接和重复拉取。正确做法是用 OpenTelemetry Collector 做指标汇聚:
- Collector 的
receiver配置prometheus类型,指向所有kratos服务的/metrics端点(通过服务发现或静态配置) - Collector 的
exporter配置prometheusremotewrite,把聚合后的指标推给 Prometheus 远程写(比 pull 更稳定) - 注意 Collector 默认不启用指标接收,需在
config.yaml显式开启:receivers: { prometheus: {} } - Collector 的
service.pipelines.metrics必须包含该 receiver 和 exporter,否则指标静默丢弃
自定义业务指标必须用 otel/metric API,不能混用 prometheus/client_golang
kratos 的 metrics 接口是适配层,底层可插拔。但如果你要上报符合 OpenTelemetry 语义约定的指标(比如和 tracing 关联、带 service.name resource 属性),必须绕过 kratos/metrics,直接用 go.opentelemetry.io/otel/metric SDK:
- 初始化时调用
otel.GetMeterProvider().Meter("your-service-name"),不要自己 newprometheus.Meter - 使用
Int64Counter、Float64Histogram等标准 instrument,它们会自动携带service.name、telemetry.sdk.language等 resource 属性 - 避免在 handler 里反复调用
meter.Int64Counter("xxx").Add()—— 应复用 counter 实例,否则创建开销大且 label 组合爆炸 - 若同时上报 tracing + metrics,确保用同一个
context.Context传递 trace ID,否则无法在 Grafana 中下钻关联
真正容易被忽略的是资源属性(resource)的一致性。Kratos 启动时默认注入的 service.name 和 service.version 只影响 tracing,不影响 metrics。如果 metrics 指标里没有 service.name,Prometheus 查询时就无法按服务维度聚合,Grafana 面板也分不出哪个是订单服务、哪个是用户服务。这个必须在 otel.InitMeterProvider 时显式传入 resource.WithAttributes 补齐。











