I have several async api calls combined together in a completable futures chain. Each stage depends on the previous stage, i.e. if the previous call returned non-empty data, then we skip next call or make a call otherwise.
I want to measure not only the total time spent on the whole chain execution but also time spent on each api call individually.
How one can achieve that?
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureApiCallsExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
var chain = apiCall1()
.thenCompose(result1 -> {
if (result1.isEmpty()) {
return apiCall2();
} else {
return CompletableFuture.completedFuture(result1);
}
})
.thenCompose(result2 -> {
if (result2.isEmpty()) {
return apiCall3();
} else {
return CompletableFuture.completedFuture(result2);
}
})
.thenApply(CompletableFutureApiCallsExample::finalMapping);
System.out.println(chain.get()); // return result
}
private static CompletableFuture<String> apiCall1() {
return CompletableFuture.supplyAsync(() -> "API Call 1 result");
}
private static CompletableFuture<String> apiCall2() {
return CompletableFuture.supplyAsync(() -> "API Call 2 result");
}
private static CompletableFuture<String> apiCall3() {
return CompletableFuture.supplyAsync(() -> "API Call 3 result");
}
private static String finalMapping(String result) {
// do mapping and return result;
return "Final result";
}
You can keep a
Map<Call, Instant> timestampswith an enumCallso in the end you have something like
which will allow you to see how long each call took as well as the overall thing.
To do this, you can create something like a
CallTimerwhich allows you to wrap each individualCompletableFutureinto the associated enum value, likeand then for each call you perform in the main function, you use the timer's
wrapinstead.I have not actually run or even compiled this so there's probably going to be some issues, but the general concept should be sound. You can also extend the
enumandwrap()to trackAPI_CALL_1_STARTandAPI_CALL_1_ENDby adding anotherthenApply()to put the end time after call completion.