Spring Boot应用如何导出DropWizard采集的Prometheus格式指标
你当前访问的/metrics端点绑定的是Dropwizard原生的com.codahale.metrics.servlets.MetricsServlet,该组件仅会返回Dropwizard自有的点分隔命名的JSON格式指标,和Prometheus要求的文本exposition格式完全无关。你虽然在代码中引入了DropwizardExports依赖,但既没有完成该组件与Prometheus采集注册中心的绑定,也没有注册Prometheus官方提供的指标导出Servlet,因此符合规范的指标端点从未真正对外暴露。
1. 确认依赖完整性
检查build.gradle中已引入所有必要依赖,避免缺失核心包导致逻辑不生效:
dependencies { // 原有依赖保留 implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'com.ryantenney.metrics:metrics-spring:3.2.0' // 匹配@EnableMetrics注解的对应版本 implementation 'io.dropwizard.metrics:metrics-core:4.2.19' implementation 'io.dropwizard.metrics:metrics-jvm:4.2.19' // JVM指标集所在包 implementation 'io.dropwizard.metrics:metrics-servlets:4.2.19' // CpuProfileServlet所在包 // Prometheus相关依赖 implementation 'io.prometheus:simpleclient:0.16.0' implementation 'io.prometheus:simpleclient_dropwizard:0.16.0' implementation 'io.prometheus:simpleclient_servlet:0.16.0' }
如果之前引入了Spring Boot Actuator自带的micrometer-prometheus相关依赖,建议先排除,避免和手动配置的Dropwizard桥接逻辑产生注册冲突。
2. 正确完成Dropwizard与Prometheus的桥接注册
DropwizardExports不能仅作为普通Spring Bean实例化,必须注册到Prometheus的CollectorRegistry才能生效,注册过程会自动加载Dropwizard采集的所有指标,同时完成指标名格式转换(点、横杠自动替换为下划线,符合Prometheus命名规范):
import com.codahale.metrics.MetricRegistry; import io.prometheus.client.CollectorRegistry; import io.prometheus.client.dropwizard.DropwizardExports; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MetricsConfig { // 原有MetricRegistry配置保留,无需修改已挂载的JVM指标集、自定义Counter等逻辑 @Bean public MetricRegistry metricRegistry() { MetricRegistry metricRegistry = new MetricRegistry(); metricRegistry.registerAll(new GarbageCollectorMetricSet()); metricRegistry.registerAll(new MemoryUsageGaugeSet()); metricRegistry.registerAll(new ThreadStatesGaugeSet()); return metricRegistry; } // 新增:注册Prometheus采集注册中心,完成Dropwizard桥接 @Bean public CollectorRegistry prometheusCollectorRegistry(MetricRegistry metricRegistry) { CollectorRegistry defaultRegistry = CollectorRegistry.defaultRegistry; // 桥接Dropwizard指标到Prometheus,自动完成名称格式转换 new DropwizardExports(metricRegistry).register(defaultRegistry); return defaultRegistry; } }
3. 注册Prometheus官方指标导出Servlet
注意不要和Dropwizard自带的同名MetricsServlet混淆,必须使用io.prometheus.client.exporter.MetricsServlet,可选择绑定到独立路径避免和原有Dropwizard端点冲突,也可以直接替换原有/metrics路径的绑定:
import io.prometheus.client.exporter.MetricsServlet; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class PrometheusServletConfig { @Bean public ServletRegistrationBean<MetricsServlet> prometheusMetricsEndpoint(CollectorRegistry collectorRegistry) { ServletRegistrationBean<MetricsServlet> registration = new ServletRegistrationBean<>(); registration.setServlet(new MetricsServlet(collectorRegistry)); // 若要直接复用/metrics路径,先删除原有Dropwizard MetricsServlet的绑定配置,再修改此处映射即可 registration.addUrlMappings("/prometheus/metrics"); return registration; } }
启动应用后访问绑定的Prometheus指标路径,返回内容符合以下格式即为配置成功:
# HELP jvm_gc_collection_seconds Time spent in a given JVM garbage collector in seconds. # TYPE jvm_gc_collection_seconds summary jvm_gc_collection_seconds_count{gc="PS MarkSweep",} 2.0 jvm_gc_collection_seconds_sum{gc="PS MarkSweep",} 0.123 # HELP my_index_seconds # TYPE my_index_seconds summary my_index_seconds_count 0.0 my_index_seconds_sum 0.0
返回内容自带# HELP、# TYPE标注,所有指标名均为下划线分隔,直接配置Prometheus抓取该端点即可正常采集。
- 两个不同包下的
MetricsServlet类名完全一致,导包时必须确认是Prometheus包下的实现,否则会一直返回Dropwizard原生JSON格式 - 实例化
DropwizardExports后必须调用register()方法绑定到CollectorRegistry,否则不会输出任何桥接的Dropwizard指标 - 你在
@Timed注解中配置的my-index名称会被自动转换为my_index前缀的Prometheus指标名,无需手动修改注解配置
内容的提问来源于stack exchange,提问作者gstackoverflow

