基于Quarkus使用MicroProfile Metrics统计异常数量不生效问题
问题根源
- MicroProfile Metrics的
@Counted注解仅对CDI托管Bean的公共方法生效,你自定义的异常类不属于Quarkus CDI容器管理的对象,构造方法被调用时不会被Quarkus的AOP拦截器捕获,所以注解完全不生效,计数器自然不会累加。
可行解决方案
方案1:手动调用Counter统计(最直接,适配自定义异常场景)
不用依赖注解,直接在异常构造方法中手动获取指标注册表并更新计数器:
import org.eclipse.microprofile.metrics.Counter; import org.eclipse.microprofile.metrics.MetricRegistry; import io.quarkus.arc.Arc; public class MyException extends RuntimeException { private static final Counter errorCounter; // 静态初始化时从CDI容器获取MetricRegistry和Counter static { MetricRegistry registry = Arc.container().instance(MetricRegistry.class).get(); errorCounter = registry.counter("errorCounterMetric", "description", "Meter metric for exception description"); } public MyException(final String errorMsg, final Throwable exception) { super(errorMsg, exception); // 构造方法执行时手动累加计数器 errorCounter.inc(); } }
注意:如果你的Quarkus版本开启了CDI懒加载,要确保
MetricRegistry已经被初始化,也可以把Counter的获取逻辑移到构造方法第一次调用时懒加载。
方案2:全局异常拦截器统一统计(更规范,适合统计所有异常的场景)
如果需要统计所有抛出的异常,不需要给每个自定义异常加逻辑,可以直接用JAX-RS的ExceptionMapper做全局拦截,统一计数:
import org.eclipse.microprofile.metrics.annotation.Counted; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; @Provider public class GlobalExceptionMapper implements ExceptionMapper<Exception> { @Override @Counted(name = "errorCounterMetric", description = "Meter metric for exception description") public Response toResponse(Exception e) { // 这里可以加你原来的异常处理逻辑,比如包装错误返回值 return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity(e.getMessage()) .build(); } }
- 这个方案的好处是所有异常走到全局拦截器的时候都会自动触发计数,不需要改任何异常类的代码,还可以针对不同异常类型定义不同的计数器,维护成本更低。
方案3:复用Quarkus内置异常指标
如果你不需要自定义特殊逻辑,Quarkus自带的HTTP请求指标已经包含了异常返回的统计,直接复用http_server_requests_seconds_count指标,过滤status=5xx的维度即可拿到异常请求的总数。
内容的提问来源于stack exchange,提问作者gayashanbc
相关产品推荐
相关产品推荐

