首页 > 解决方案 > Microprofile (SmallRye) @Gauge 但不被度量基础设施调用

问题描述

我在一个使用 Quarkus 版本 1.7.3 的项目中为 Eclipse Microprofile Metrics 使用 SmallRye 实现。我需要收集 ApplicationScoped 类中的方法返回的随机整数值作为指标,但是当我使用 @Gauge 时,指标基础结构会调用该方法。它对我不起作用,因为我需要为该方法提供一个参数,这样它才有意义。当我自己的应用程序而不是 Microprofile 实现调用该方法时,有没有办法收集这个指标?

在我的场景中,我将一个项目发送到外部 API 并等待他们使用我的 API 进行响应。这是异步的,至少需要 2 分钟,平均 5 到 6 分钟,但有时可能需要几分钟。所以当我收到响应时,我首先从我的数据库中检索项目,然后在我做任何我需要做的事情之前,我调用方法 timeWaitingForResponseMinutes 传递我刚刚从数据库中检索到的项目作为参数:

    @Gauge(name = "timeWaitingForResponseMinutes", description = "Time waiting for a response for the Item in minutes", unit = MetricUnits.NONE)
    public Integer timeWaitingForResponseMinutes(Item item) {
        Timestamp nowTimestamp = Timestamp.from(Instant.now());
        long nowMilliseconds = nowTimestamp.getTime();
        long itemMilliseconds = item.getTimestampItemSent().getTime();
        Integer minutesWaiting = (int)((nowMilliseconds - itemMilliseconds) / (60 * 1000));
        return minutesWaiting;
    }

这个项目有一个名为 timestampItemSent 的 java.sql.Timestamp 字段,我用它来与当前时间进行比较。@Gauge 不能那样工作,因为该方法应该没有参数。我收到错误消息:无法导出指标 company_controller_ItemController_timeWaitingForResponseMinutes: java.lang.IllegalArgumentException

任何帮助将不胜感激。

标签: javaquarkusmicroprofilesmallrye

解决方案


本质上,您需要对由代码中的两种不同方法定义的跨度进行计时,一种用于启动跨度,一种用于结束跨度。我不认为使用注释是可行的,但是通过一些编程是可行的。您可以在 CDI bean 中注入指标,因此我将修改timeWaitingForResponseMinutes如下:

import org.eclipse.microprofile.metrics.Timer;
import java.util.concurrent.TimeUnit;

@ApplicationScoped
public class MyResponseTimer {
    @Inject
    @Metric(name = "timeWaitingForResponseMinutes", description = "Time waiting for a response for the Item in minutes", unit = MetricUnits.MINUTES)
    private Timer timer;

    public void timeWaitingForResponseMinutes(Item item) {
        Timestamp nowTimestamp = Timestamp.from(Instant.now());
        long nowMilliseconds = nowTimestamp.getTime();
        long itemMilliseconds = item.getTimestampItemSent().getTime();
        long minutesWaiting = ((nowMilliseconds - itemMilliseconds) / (60 * 1000));
        timer.update(minutesWaiting, TimeUnit.MINUTES);
    }
}

现在注入这个 bean 并随心所欲地调用timeWaitingForResponseMinutes,传递你的Item. (您将看到许多您自己的代码,但请注意,我将度量单位更改为 MINUTES 以使其有意义)


推荐阅读