问题
I'm trying to programmatically read the Meters as follows:
Get registry:
MeterRegistry registry = Metrics.globalRegistry.getRegistries().iterator().next();
Read measurement:
double systemCpuUsage = registry.get("system.cpu.usage").gauge().measure().iterator().next().getValue();
The problem is that sometimes I get NaN
.
I read about this in the docs: Why is my Gauge reporting NaN or disappearing?
but I'm not sure what I shall do. Also, I'm reading the "built-in" gauge of Spring Boot actuator (which is exposed by management.metrics.enable.process.cpu.usage=true
) so I cannot change it's construction.
回答1:
In this case, since you are using a "built in" metric, you can override io.micrometer.core.instrument.binder.MeterBinder#bindTo
, redefine system.cpu.usage
with a a custom MeterBinder implementation, and defining system.cpu.usage as (along with others which you use)
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);
Refer io.micrometer.core.instrument.binder.system.ProcessorMetrics
for example which defines it as of now.
The bean on ProcessorMetrics is defined in org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration
, you need to define your bean too somewhere. (or mark @Component)
If you don't want to rely on some predefined metric by micrometer, like to capture some custom list size, this is what you can do.
private static Map<String, Long> strongRefGauge = new ConcurrentHashMap<>();
For adding values do the following
registry.gauge("CustomListSizeGuage", getMyCustomGuageTagsFor("myListName"), strongRefGauge, g -> g.get("myListName")).put("myListName", list.size());
回答2:
This is due to Micrometer using 'weak references' in gauges. Since the gauge doesn't hold a strong reference to the object, when the object is garbage collected, the value becomes NaN
.
If you did control the gauge creation you would want to store a reference yourself, or call strongReference(true)
on the gauge.
If you are encountering with the built in Spring Boot gauges, I believe you are running into a bug. Which is very strange since the ProcessorMetrics
meter binder that creates that gauge holds its own reference (though it is nullable).
Are you running on a different JVM or Runtime environment when you see the NaN
?
来源:https://stackoverflow.com/questions/56889240/why-do-reading-micrometer-measurement-returns-nan-sometimes