You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Micronaut应用:如何在Prometheus端点调用时触发指标计算?

Micronaut集成Micrometer Prometheus:按需计算指标解决方案

问题根源

你的代码存在两个关键问题:

  1. Prototype Bean未被实例化:Micronaut不会自动创建Prototype类型的Bean,除非你主动注入或通过BeanContext获取它,所以构造函数里的指标注册代码根本没执行。
  2. Gauge用法错误:直接传入固定值12的方式不符合Gauge的设计逻辑,而且这种写法也无法实现「Prometheus端点调用时才计算指标」的需求。

正确实现方式

下面提供两种可行的实现方案,满足你按需计算指标的需求:

方案一:自定义MeterBinder+端点拦截

适合复用默认的/prometheus端点,在请求到达时触发指标计算:

  1. 确认依赖已引入(以build.gradle为例):
implementation("io.micronaut.micrometer:micronaut-micrometer-core")
implementation("io.micronaut.micrometer:micronaut-micrometer-registry-prometheus")
runtimeOnly("io.micrometer:micrometer-registry-prometheus")
  1. 实现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;
    }
}
  1. 编写过滤器拦截/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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 06:10:30