Microprofile (SmallRye) @Gauge 但未被指标基础设施调用

Microprofile (SmallRye) @Gauge but not invoked by the metrics infrastructure

我在一个使用 Quarkus 1.7.3 版本的项目中使用 SmallRye 实现 Eclipse Microprofile Metrics。我需要收集一个由 ApplicationScoped class 中的方法返回的随机整数值作为指标,但是当我使用 @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

非常感谢任何帮助。

本质上,您需要的是对代码中由两种不同方法定义的跨度进行计时,一种用于开始跨度,一种用于结束跨度。我不认为它可以通过注释来实现,但是通过一些编程是可行的。您可以在 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 以使其有意义)