I'd like to use Micrometer to record the execution time of an async method when it eventually happens. Is there a recommended way to do this?
Example: Kafka Replying Template. I want to record the time it takes to actually execute the sendAndReceive call (sends a message on a request topic and receives a response on a reply topic).
public Mono<String> sendRequest(Mono<String> request) {
return request
.map(r -> new ProducerRecord<String, String>(requestsTopic, r))
.map(pr -> {
pr.headers()
.add(new RecordHeader(KafkaHeaders.REPLY_TOPIC,
"reply-topic".getBytes()));
return pr;
})
.map(pr -> replyingKafkaTemplate.sendAndReceive(pr))
... // further maps, filters, etc.
Something like
responseGenerationTimer.record(() -> replyingKafkaTemplate.sendAndReceive(pr)))
won't work here; it just records the time that it takes to create the Supplier
, not the actual execution time.
You could do something like the following:
See here for Sample documentation: http://micrometer.io/docs/concepts#_storing_start_state_in_code_timer_sample_code
For a nicer approach you could also have a look at resilience4j they decorate the mono via transform: https://github.com/resilience4j/resilience4j/tree/master/resilience4j-reactor
I used the following:
So to use it in practice:
It looks like
recordCallable
as suggested by Brian Clozel is the answer. I wrote a quick test to verify this:and to test this:
The timer reports that the execution time is roughly 1004ms with the 1000ms delay, and 4ms without it.
You could use
reactor.util.context.Context
You can just metrics() from Mono/Flux() (have a look at metrics() here: https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Flux.html) then you can do something like
And e.g. in graphite you will see latency for this call measured (You can see more here: How to use Micrometer timer together with webflux endpoints)