Hi,
I tried to add a gauge to Prometheus in my reactive project (Webflux) but it seems to add a gauge to Prometheus metrics you need to create a bean from MeterRegistryCustomizer<PrometheusMeterRegistry>
which does not support reactive; it means you need to block your call or just give up
It would be good to have a way to add gauge programmatically even without defining a bean or support a different interface to support reactive
Comment From: wilkinsona
Each MeterRegistryCustomizer
is called during application context refresh where blocking does not matter. Beyond that, Micrometer is responsible for the APIs that are used to register meters and provide their values. They made some changes a few years ago to minimise any blocking calls so we believe that the current API and implementation should be sufficient. If you have a situation where that's not the case, please open a new Micrometer issue that describe in detail the problem that you're facing, ideally illustrating it with a minimal sample application.
Comment From: ghahramani
Basically, here is what I am doing right now which it is not perfect and I think it should support the whole reactive. I am not sure why you are saying it is sufficient; it is against of reactive principal which is about blocking.
@Bean
fun diskSpaceHealth(context: ApplicationContext) = MeterRegistryCustomizer<PrometheusMeterRegistry> { registry ->
registry.gauge("health_disk_space", context) { ctx ->
val service = ctx.getBean<HealthCheckService>()
try {
service
.findStatus("diskSpace")
.block()
.toNumber()
} catch (e: Exception) {
logger.warn("Error happened while checking for disk space health", e)
0.0
}
}
}
Comment From: wilkinsona
Blocking isn't necessarily bad. It depends upon which thread it's happening on. As I said above, the API you're using here is part of Micrometer and is out of Spring Boot's control. If you have a situation where you're using Micrometer and it's retrieving the value of a Gauge
on a thread where blocking should be avoided, then please open a Micrometer issue that illustrates exactly why and when that's happening.
Comment From: ghahramani
I think I am missing something here, you keep saying the interface is for Micrometer but actually it is from the actuator project
Could you please elaborate on that why you insist this is a Micrometer interface?
https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryCustomizer.html
Comment From: wilkinsona
MeterRegistryCustomizer
isn't really relevant here. As I said above, MeterRegistryCustomizer
is called during application context refresh where blocking does not matter. You're calling io.micrometer.core.instrument.MeterRegistry.gauge(String, T, ToDoubleFunction<T>)
and it's within your ToDoubleFunction
implementation that you're calling block()
. The ToDoubleFunction
is not called by Spring Boot. It is called by Micrometer when it needs the value of the gauge. Whether or not it matters that this is blocking depends upon the thread on which Micrometer retrieves the gauge's value.