Search code examples
javareactive-programmingspring-webfluxreactor

Time elapsed time in Mono calls, mapping both success and error cases


I'm using a WebClient to call a downstream service, and I would like to log the elapsed time of the calls, both in the case of success and in the case of error.

The elapsed and timed operators work fine for the success case, but when you have an error, e.g., a 500 returned from the downstream service, or a timeout, the subscriber receives just a throwable, not a throwable + elapsed time.

Is there a way to fix this?


Solution

  • There's no "simple" way I'm aware of to do this in a general case for errors in a reactive stream. Once an error occurs that's it - you break outside of the normal reactive flow, timings included, so that information is lost.

    However, an alternative in the case of webclient specifically would be to make sure you don't throw the error at all, using the exchange() rather than retrieve() semantics, similar to:

    client.get()
            .uri("https://httpstat.us/500")
            .exchangeToMono(cr -> cr.bodyToMono(String.class))
            .timed()
            .doOnNext(s -> {
                System.out.println("ELAPSED: " + s.elapsedSinceSubscription().toMillis());
            });