Skip to content

Instantly share code, notes, and snippets.

@Toparvion
Created November 19, 2021 02:55
Show Gist options
  • Save Toparvion/90ebbdef9d31185a785670d9c2a86762 to your computer and use it in GitHub Desktop.
Save Toparvion/90ebbdef9d31185a785670d9c2a86762 to your computer and use it in GitHub Desktop.
A simple WebFilter (from Spring WebFlux framework) for correct handling of 'rid' URL query parameter as a similarly-named MDC entry (even in threads spawned by Reactor's Schedulers)
package pro.toparvion.sample.gateway.gatewaydemo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import static org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type.REACTIVE;
@Component
@ConditionalOnWebApplication(type = REACTIVE)
public class ReactiveMdcFilter implements WebFilter {
private static final Logger log = LoggerFactory.getLogger(ReactiveMdcFilter.class);
private static final String RID = "rid";
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
String rid = exchange.getRequest().getQueryParams().getFirst(RID);
return chain.filter(exchange)
.doOnSubscribe(subscription -> {
MDC.put(RID, rid);
log.trace("rid={} has been set in filter", rid);
})
.doFinally(whatever -> {
MDC.remove(RID);
log.trace("rid={} has been removed in filter", rid);
});
}
@PostConstruct
void setupReactorThreadsDecorator() {
Schedulers.onScheduleHook("mdc", runnable -> {
String rid = MDC.get(RID);
return () -> {
MDC.put(RID, rid);
log.trace("'rid' mark has been assigned to the thread");
try {
runnable.run();
} finally {
MDC.remove(RID);
log.trace("'rid' mark removed from the thread");
}
};
});
log.info("Reactive MDC hook has been set");
}
@PreDestroy
void shutdownThreadsDecorator() {
Schedulers.resetOnScheduleHook("mdc");
log.info("Reactive MDC hook has been removed");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment