Will updating a micrometer gauge ever block the calling thread (eg perform I/O)?
I believe the answer is "no, I/O happens in a separate metrics collection thread" but would like to know of exceptions to this, edge cases, ..
Thanks Tarik
Will updating a micrometer gauge ever block the calling thread (eg perform I/O)?
I believe the answer is "no, I/O happens in a separate metrics collection thread" but would like to know of exceptions to this, edge cases, ..
Thanks Tarik
It depends what do you mean by calling thread. If you mean the user thread that registers the gauge, the answer is no, at that point the method that you feed to the gauge is not even called.
If you mean the thread that will "ship" the metrics, that will be blocked. This is usually a separate thread (since most of the registries are push based) but in case of Prometheus (which is pull-based) the gauge will block the Prometheus endpoint and the thread that serves it.
For this reason, in Micrometer, instead of registering the blocking method to the gauge, you can have an intermediate "state" object that you update periodically from a separate thread (blocking) and read it from the gauge (non-blocking), e.g.:
AtomicInteger currentValue = registry.gauge("test.gauge", new AtomicInteger(0));
And you can modify the currentValue
from another thread, see the docs
You can do this with any arbitrary objects, e.g.:
State state = registry.gauge("test.gauge", Collections.emptyList(), new State(), State::getValue);
Where getValue
does not block just give you the latest value while on another thread you can update the value encapsulated in the State
object.
Here are a few lines showing that the method you register into the gauge is blocking:
public class GaugeSample {
public static void main(String[] args) throws InterruptedException {
PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
System.out.println("registering the gauge...");
Gauge.builder("test.gauge", GaugeSample::getValue)
.register(registry);
System.out.println("scraping...");
System.out.println(registry.scrape());
}
private static double getValue() {
try {
Thread.sleep(5_000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
return 42;
}
}