Micronaut应用:如何在Prometheus端点调用时触发指标计算?
Micronaut集成Micrometer Prometheus:按需计算指标解决方案
问题根源
你的代码存在两个关键问题:
- Prototype Bean未被实例化:Micronaut不会自动创建Prototype类型的Bean,除非你主动注入或通过
BeanContext获取它,所以构造函数里的指标注册代码根本没执行。 - Gauge用法错误:直接传入固定值12的方式不符合Gauge的设计逻辑,而且这种写法也无法实现「Prometheus端点调用时才计算指标」的需求。
正确实现方式
下面提供两种可行的实现方案,满足你按需计算指标的需求:
方案一:自定义MeterBinder+端点拦截
适合复用默认的/prometheus端点,在请求到达时触发指标计算:
- 确认依赖已引入(以build.gradle为例):
implementation("io.micronaut.micrometer:micronaut-micrometer-core") implementation("io.micronaut.micrometer:micronaut-micrometer-registry-prometheus") runtimeOnly("io.micrometer:micrometer-registry-prometheus")
- 实现
MeterBinder管理指标:
import io.micrometer.core.instrument.Gauge; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.binder.MeterBinder; import jakarta.inject.Singleton; @Singleton public class SampleMetricBinder implements MeterBinder { // volatile保证多线程下指标值的可见性 private volatile int sampleValue; @Override public void bindTo(MeterRegistry registry) { // 将Gauge绑定到取值方法,每次Prometheus拉取时都会获取最新值 Gauge.builder("SampleMetric", this, SampleMetricBinder::getSampleValue) .description("自定义示例指标") .register(registry); } public int getSampleValue() { return sampleValue; } // 触发指标计算的方法,在端点请求时调用 public void calculateMetric() { // 替换为你的实际业务计算逻辑,比如查询数据库、调用接口等 this.sampleValue = 12; } }
- 编写过滤器拦截
/prometheus请求,触发计算:
import io.micronaut.http.HttpRequest; import io.micronaut.http.MutableHttpResponse; import io.micronaut.http.annotation.Filter; import io.micronaut.http.filter.HttpServerFilter; import io.micronaut.http.filter.ServerFilterChain; import org.reactivestreams.Publisher; @Filter("/prometheus") public class PrometheusEndpointFilter implements HttpServerFilter { private final SampleMetricBinder metricBinder; // 构造注入 public PrometheusEndpointFilter(SampleMetricBinder metricBinder) { this.metricBinder = metricBinder; } @Override public Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> request, ServerFilterChain chain) { // 在返回指标前先计算最新值 metricBinder.calculateMetric(); return chain.proceed(request); } }
方案二:自定义指标端点
如果不需要使用默认的/prometheus端点,可以自行编写控制器处理:
import io.micrometer.core.instrument.MeterRegistry; import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; import jakarta.inject.Inject; @Controller("/custom-metrics") public class CustomMetricsController { @Inject private MeterRegistry registry; @Get public String getMetrics() { // 先执行指标计算逻辑 int calculatedValue = 12; // 替换为你的业务逻辑 // 更新或创建指标 registry.gauge("SampleMetric", calculatedValue); // 返回Prometheus格式的指标内容 return ((io.micrometer.prometheus.PrometheusMeterRegistry) registry).scrape(); } }
配置注意事项
别忘了在application.yml中启用Prometheus端点:
micronaut: endpoints: prometheus: enabled: true sensitive: false # 生产环境建议设为true,并配合权限控制 micrometer: export: prometheus: enabled: true
额外提醒:指标是全局唯一的,用Singleton Bean管理即可,无需使用Prototype Bean;Gauge的正确用法是绑定可变数据源,这样每次Prometheus拉取时都能获取最新计算的值。
内容的提问来源于stack exchange,提问作者Aarij Siddiqui
相关产品推荐
相关产品推荐

