如何避免Micrometer/Prometheus中的测量值变成NaN?

8

我想要监控已登录的用户,我正在调用API获取已登录用户的信息,以下是我使用的代码:

public class MonitorService {
    private InfoCollectionService infoService;
    public MonitorService(InfoCollectionService infoService) {
        this.infoService = infoService
    }

    @Scheduled(fixedDelay = 5000)
    public void currentLoggedInUserMonitor() {
        infoService.getLoggedInUser("channel").forEach(channel -> {
            Metrics.gauge("LoggedInUsers.Inchannel_" + channel.getchannelName(), channel.getgetLoggedInUser());
        });
    }
}

我看到了Prometheus里的值,但问题是过几秒钟后,这些值变成NaN。我读到Micrometer的仪表会在obj输入上使用WeakReference(因此会被垃圾回收)。我不知道该怎么解决这个问题。如果有人知道如何解决这个问题,那将是非常好的。

1个回答

5

这是Micrometer的一个缺陷,我希望最终能够修复。

同时,您需要将值保留在映射中,以避免垃圾收集。请注意,我们随后将计量器指向映射,并使用lambda表达式提取值以避免垃圾收集。

public class MonitorService {
    private Map<String, Integer> gaugeCache = new HashMap<>();
    private InfoCollectionService infoService;
    public MonitorService(InfoCollectionService infoService) {
        this.infoService = infoService
    }

    @Scheduled(fixedDelay = 5000)
    public void currentLoggedInUserMonitor() {
        infoService.getLoggedInUser("channel").forEach(channel -> {
            gaugeCache.put(channel.getchannelName(), channel.getgetLoggedInUser());
            Metrics.gauge("LoggedInUsers.Inchannel_" + channel.getchannelName(), gaugeCache, g -> g.get(channel.getchannelName()));
        });
    }
}

我建议使用标签来区分不同的渠道:

Metrics.gauge("loggedInUsers.inChannel", Tag.of("channel",channel.getchannelName()), gaugeCache, g -> g.get(channel.getchannelName()));

1
尝试使用相同的模式但没有成功。不明白为什么要将整个地图传递到仪表中。 - Logemann
这真的帮了我很多!分享一下,根据文档,我必须使用强引用:“如果您看到仪表报告几分钟后消失或报告NaN,那么几乎可以肯定地表示被计量的底层对象已被垃圾收集。” https://micrometer.io/docs/concepts#_why_is_my_gauge_reporting_nan_or_disappearing 在我的情况下,解决问题就像使用实例变量一样简单,这立即修复了它。 - PlunkettBoy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接