I need to show context values in logs of the whole application. I tried to do it in this method: "searchStudents" but I got not success. It seems when do step ".doOnComplete()" the subscriberContext is lost and I need and alternative. Have somebody some solution to propose me??
Controller
@GetMapping(value = "{userId}/searchStudents")
public Flux<Student> searchStudents(
@ModelAttribute(USER_CONTEXT_REQUEST_ATTRIBUTE) Context userContext,
@PathVariable String userId,
@RequestParam String lang,
@RequestParam String studentName) {
return coursesProvider.searchStudents(userId, lang, studentName).subscriberContext(userContext);
logUtils
public class LogUtils {
public static <T> Consumer<Signal<T>> logOnNext(Consumer<T> logStatement) {
return signal -> {
if (!signal.isOnNext())
return;
Optional<String> teacherIdMaybe = signal.getContext().getOrEmpty("TEACHER_ID");
if (teacherIdMaybe.isPresent()) {
try (MDC.MDCCloseable teacherIdMdcCloseable = MDC.putCloseable("TEACHER_ID", teacherIdMaybe.get())) {
logStatement.accept(signal.get());
}
} else {
logStatement.accept(signal.get());
};
};
}
}
Service
@Override
public Flux<Student> searchStudents(String userId, String lang, String studentName) {
AtomicInteger counter = new AtomicInteger();
return Mono.just(String.format(">>> Searching student named: %s. <<<", studentName))
.doOnEach(logOnNext(LOGGER::info)) // well logged
.thenMany(webClient.get()
.uri(uriBuilder -> uriBuilder
.path("/v1/users/{userId}/courses/searchStudents/{lang}/{studentName}")
.build(userId, lang, studentName))
.accept(APPLICATION_JSON)
.retrieve()
.bodyToFlux(Student.class)
.filter(Student::isEligible)
.doOnNext(p -> counter.incrementAndGet())
// this is the ligne that I need to change
.doOnComplete(() -> LOGGER.info("{} students found", counter.get()))
);
}
My tries:
- Return a Flux of String
.then( Mono.just(String.format("%s students found", counter.get())) .doOnEach(logOnNext(LOGGER::info)))
- No log
.doOnComplete(() -> Mono.just(String.format("%s students found", counter.get())) .doOnEach(logOnNext(LOGGER::info)) .then() // no log .subscribe() // log without MDC )
- Every count is logged and I want final count
.doOnEach(logOnNext( x -> LOGGER.info("{} students found", counter.get()))