I have the following interceptor that tracks request/response based on saving and restoring some vars stored in MDC context for every request.
public class LoggingInterceptor implements DeferredResultProcessingInterceptor {
private final HelloSeeYouLogger helloSeeYouLogger;
private static final String X_UOW = "X-UOW";
private static final String X_REQUEST_ID = "X-RequestId";
private Map<String, String> context;
public LoggingInterceptor(HelloSeeYouLogger helloSeeYouLogger) {
this.helloSeeYouLogger = helloSeeYouLogger;
}
@Override
public <T> void beforeConcurrentHandling(NativeWebRequest request, DeferredResult<T> deferredResult) {
addUowAndRequestIdToMDC(request.getHeader(X_UOW), request.getHeader(X_REQUEST_ID));
final String uri = getUri((HttpServletRequest) request.getNativeRequest());
helloSeeYouLogger.logHelloThere(uri);
context = MDC.getCopyOfContextMap();
}
@Override
public <T> void afterCompletion(NativeWebRequest request, DeferredResult<T> deferredResult) {
if (context != null) {
MDC.setContextMap(context);
}
final String uri = getUri((HttpServletRequest) request.getNativeRequest());
String body = getBody((HttpServletRequest) request.getNativeRequest());
if (!StringUtils.isEmpty(body)) {
body = replaceMoreThanOneSpacesWithOneSpace(hideCreditCardNumber(body));
}
helloSeeYouLogger.logSeeYou(uri, body);
clearUowAndRequestIdFromMDC();
}
public static void addUowAndRequestIdToMDC(final String uow, final String requestId) {
//This NewRelic stuff shouldn't be here as it is used for distributed tracing and not logging.
// However it helps to levarage requests tracking from a metric service such as new relic to a log aggregation service
//such as ELK.
NewRelic.addCustomParameter(UOW, uow);
NewRelic.addCustomParameter(REQUEST_ID, requestId);
MDC.put(UOW, uow);
MDC.put(REQUEST_ID, requestId);
}
public static void clearUowAndRequestIdFromMDC() {
if (MDC.get(UOW) != null) {
MDC.remove(UOW);
}
if (MDC.get(REQUEST_ID) != null) {
MDC.remove(REQUEST_ID);
}
}
I think i mn going to have concurrency problems as context is an instance variable and when running multiple concurrent thread saving and restoring MDC context will result in wrong results. Also using synchronize keyword will add performance problems. I was wondering if there is a better approach to track MDC context when a spring controller returns a DeferredResult.
Thanks