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

Quarkus中Micrometer Gauge指标不显示或为NaN问题求助

解决Micrometer Gauge无法更新数据库指标的问题

你的问题核心是Micrometer Gauge绑定了不可变的Integer对象,导致后续值更新无法被追踪,而且每次调用方法都重复注册Gauge,这也会引发异常或指标不更新的问题。以下是具体的修复方案:

问题分析

  1. Integer是不可变类型,每次赋值都会生成新的实例。你在registerMetricSalesByPaymentMode里把当前的Integer值传给registry.gauge(),Gauge只会持有这个旧实例的引用,后续metricSalesByPaymentModeEfectiu更新为新的Integer时,Gauge完全感知不到。
  2. 每次调用方法都注册同名同标签的Gauge,Micrometer会忽略重复注册的请求,导致新值无法生效。

修复方案

1. 使用可变数值类型替代Integer

用Micrometer提供的MutableInteger(或JDK的AtomicInteger)作为指标的存储对象,这类可变类型允许Gauge持续追踪值的变化。

2. 初始化时一次性注册Gauge

在Bean构造时完成Gauge的注册,后续只需要更新可变对象的值即可,无需重复注册。

修改后的完整代码

@ApplicationScoped
public class OperationalMetricsBO {

    private final String METIC_NAME_PREFIX = "telecomandament.ticketing.api.";
    private final String METRIC_NAME_SALES_BY_PAYMENT_MODE = METIC_NAME_PREFIX+"sales.by.payment.mode";
    private final MeterRegistry registry;
    
    // 用Micrometer的可变数值类型存储指标值,初始化为0
    private final MutableInteger metricSalesByPaymentModeEfectiu = new MutableInteger(0);
    private final MutableInteger metricSalesByPaymentModeTargeta = new MutableInteger(0);
    

    public OperationalMetricsBO(MeterRegistry registry){
        this.registry = registry;
        // 初始化时注册Gauge,绑定到可变对象
        registry.gauge(METRIC_NAME_SALES_BY_PAYMENT_MODE, 
                       Tags.of("PaymentModeName", PaymentMode.EFECTIU.getName()), 
                       metricSalesByPaymentModeEfectiu);
        registry.gauge(METRIC_NAME_SALES_BY_PAYMENT_MODE, 
                       Tags.of("PaymentModeName", PaymentMode.TARGETA_CREDIT.getName().replace(" ", "_")), 
                       metricSalesByPaymentModeTargeta);
    }   
    
    /**
     * 查询数据库并更新指标值(无需重复注册Gauge)
     * @return
     */
    public List<SalesByPaymentModeDTO> updateMetricSalesByPaymentMode() {
        // 替换为你的数据库查询计算逻辑
        int efectiuValue = CALCULATION__CODE;
        int targetaValue = CALCULATION__CODE;
        
        // 直接更新可变对象的值,Gauge会自动同步最新值
        metricSalesByPaymentModeEfectiu.set(efectiuValue);
        metricSalesByPaymentModeTargeta.set(targetaValue);
    
        return salesByPaymentModeList;
    }
}

关键说明

  • MutableInteger vs AtomicInteger:两者都是线程安全的可变数值类型,MutableInteger是Micrometer专为指标场景设计的,使用更简洁;如果想用JDK原生类,替换成AtomicInteger也是完全可行的,注册方式相同。
  • 避免重复注册:重复注册同名同标签的Gauge会被Micrometer忽略,所以必须在Bean初始化时完成注册,后续只更新值。
  • 方法职责优化:修改后的方法只负责更新指标值,职责更单一,也符合指标组件的设计规范。

另外,确实建议Quarkus文档补充这类从数据库动态更新指标的场景示例,帮助开发者避开这类常见的使用误区。

内容的提问来源于stack exchange,提问作者esteveavi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 18:13:32