为什么有时读取千分尺测量 returns NaN?
Why do reading Micrometer measurement returns NaN sometimes?
我正在尝试以编程方式读取仪表,如下所示:
获取注册表:
MeterRegistry registry = Metrics.globalRegistry.getRegistries().iterator().next();
读取测量值:
double systemCpuUsage = registry.get("system.cpu.usage").gauge().measure().iterator().next().getValue();
问题是有时我得到 NaN
。
我在文档中读到了这个:Why is my Gauge reporting NaN or disappearing?
但我不确定我该做什么。另外,我正在阅读 Spring 引导执行器的 "built-in" 仪表(由 management.metrics.enable.process.cpu.usage=true
公开),因此我无法更改其结构。
这是由于 Micrometer 在量规中使用了 'weak references'。由于仪表没有对对象的强引用,当对象被垃圾回收时,该值变为 NaN
.
如果您确实控制了仪表的创建,您会希望自己存储一个参考,或者在仪表上调用 strongReference(true)
。
如果您遇到内置 Spring 启动仪表,我相信您 运行 遇到了错误。这很奇怪,因为创建该仪表的 ProcessorMetrics
仪表绑定器拥有自己的引用(尽管它可以为空)。
当您看到 NaN
时,您是否 运行 在不同的 JVM 或运行时环境中?
在这种情况下,由于您使用的是 "built in" 指标,因此您可以覆盖 io.micrometer.core.instrument.binder.MeterBinder#bindTo
,使用自定义 MeterBinder 实现重新定义 system.cpu.usage
,并将 system.cpu.usage 定义为(以及您使用的其他人)
Gauge.builder("system.cpu.usage", operatingSystemBean, x -> invoke(systemCpuUsage))
.strongReference(true)//Add strong reference
.tags(tags)
.description("The recent cpu usage for the whole system")
.register(registry);
参考 io.micrometer.core.instrument.binder.system.ProcessorMetrics
示例,它定义了它。
ProcessorMetrics 上的 bean 在 org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration
中定义,您也需要在某处定义您的 bean。 (或标记@Component)
如果您不想依赖某些预定义的千分尺指标,例如捕获一些自定义列表大小,这就是您可以做的。
private static Map<String, Long> strongRefGauge = new ConcurrentHashMap<>();
要添加值,请执行以下操作
registry.gauge("CustomListSizeGuage", getMyCustomGuageTagsFor("myListName"), strongRefGauge, g -> g.get("myListName")).put("myListName", list.size());
只想提及另一个可能导致千分尺报告 NaN 的原因。它实际上是一种默认行为,当 异常从值函数本身抛出 时:https://github.com/micrometer-metrics/micrometer/blob/1.8.x/micrometer-core/src/main/java/io/micrometer/core/instrument/internal/DefaultGauge.java#L57
此异常直接在仪表本身中捕获,并且可能会记录在 WARN 或 DEBUG lvl 中,不确定,由于某种原因在我们的应用程序中无法正常工作。
所以这只是另一个值得检查的可能原因:)
我正在尝试以编程方式读取仪表,如下所示:
获取注册表:
MeterRegistry registry = Metrics.globalRegistry.getRegistries().iterator().next();
读取测量值:
double systemCpuUsage = registry.get("system.cpu.usage").gauge().measure().iterator().next().getValue();
问题是有时我得到 NaN
。
我在文档中读到了这个:Why is my Gauge reporting NaN or disappearing?
但我不确定我该做什么。另外,我正在阅读 Spring 引导执行器的 "built-in" 仪表(由 management.metrics.enable.process.cpu.usage=true
公开),因此我无法更改其结构。
这是由于 Micrometer 在量规中使用了 'weak references'。由于仪表没有对对象的强引用,当对象被垃圾回收时,该值变为 NaN
.
如果您确实控制了仪表的创建,您会希望自己存储一个参考,或者在仪表上调用 strongReference(true)
。
如果您遇到内置 Spring 启动仪表,我相信您 运行 遇到了错误。这很奇怪,因为创建该仪表的 ProcessorMetrics
仪表绑定器拥有自己的引用(尽管它可以为空)。
当您看到 NaN
时,您是否 运行 在不同的 JVM 或运行时环境中?
在这种情况下,由于您使用的是 "built in" 指标,因此您可以覆盖 io.micrometer.core.instrument.binder.MeterBinder#bindTo
,使用自定义 MeterBinder 实现重新定义 system.cpu.usage
,并将 system.cpu.usage 定义为(以及您使用的其他人)
Gauge.builder("system.cpu.usage", operatingSystemBean, x -> invoke(systemCpuUsage))
.strongReference(true)//Add strong reference
.tags(tags)
.description("The recent cpu usage for the whole system")
.register(registry);
参考 io.micrometer.core.instrument.binder.system.ProcessorMetrics
示例,它定义了它。
ProcessorMetrics 上的 bean 在 org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration
中定义,您也需要在某处定义您的 bean。 (或标记@Component)
如果您不想依赖某些预定义的千分尺指标,例如捕获一些自定义列表大小,这就是您可以做的。
private static Map<String, Long> strongRefGauge = new ConcurrentHashMap<>();
要添加值,请执行以下操作
registry.gauge("CustomListSizeGuage", getMyCustomGuageTagsFor("myListName"), strongRefGauge, g -> g.get("myListName")).put("myListName", list.size());
只想提及另一个可能导致千分尺报告 NaN 的原因。它实际上是一种默认行为,当 异常从值函数本身抛出 时:https://github.com/micrometer-metrics/micrometer/blob/1.8.x/micrometer-core/src/main/java/io/micrometer/core/instrument/internal/DefaultGauge.java#L57
此异常直接在仪表本身中捕获,并且可能会记录在 WARN 或 DEBUG lvl 中,不确定,由于某种原因在我们的应用程序中无法正常工作。
所以这只是另一个值得检查的可能原因:)