When to remove from the MDC
Asked Answered
O

1

5

I recently discovered the magic of using MDCs when logging. It works perfectly.

I have the following method:

public static final String MDC_CLIENT="client";
public static final String MDC_SESSION="session";
public static final String MDC_DEVICE="device";

// Called for every request.
public static void request(final HttpServletRequest request) {
  // The MDC is a thread-local storage accessable from the log formatter.
  MDC.put(MDC_CLIENT, String.format("%s:%s", request.getRemoteHost(), request.getRemotePort()));
  HttpSession session = request.getSession();
  MDC.put(MDC_SESSION, session.getId());
  MDC.put(MDC_DEVICE, (String)session.getAttribute("device"));
  // Also record the context.
  setContext(session.getServletContext());
}

This is called as the first action in every jsp. This allows me to keep track of the details of the session in the log nicely.

However - how do I know when to remove these map entries? What event should I watch for that will allow me to tidy up the map?

I am hosting under Tomcat. If it re-uses threads then I won't leak memory because these are essentially thread-local so each put will overwrite the old put from the last time the thread was used. If it doesn't - or I am hosted under something else that doesn't - I am essentially growing the map potentially forever - or at least until the host is restarted.

I think the essence of my question is - is there an event I can detect that indicates that a particular session or thread is finished with and about to be released.

Oslo answered 15/1, 2014 at 12:21 Comment(0)
U
9

Rather than putting the call in every JSP I would register a ServletRequestListener, which gets notified both when the request starts and when it finishes:

public class MDCListener implements ServletRequestListener {
  public void requestInitialized(ServletRequestEvent e) {
    YourUtilityClass.request((HttpServletRequest)e.getServletRequest());
  }

  public void requestDestroyed(ServletRequestEvent e) {
    YourUtilityClass.tearDown((HttpServletRequest)e.getServletRequest());
  }
}

Alternatively you could use a filter which lets you wrap around the usual request processing flow:

void doFilter(ServletRequest request, ServletResponse response,
              FilterChain chain) throws IOException, ServletException {
  setupMDC();
  chain.doFilter(request, response);
  tearDownMDC();
}

Either way you simply register the relevant classes in web.xml and the container should take care of the rest.

Unwilling answered 15/1, 2014 at 12:43 Comment(3)
Worked perfectly! I had to add <listener><listener-class>com...MDCListener</listener-class></listener> to my web.xml.Oslo
If the MDC value is not removed what will happen ?Showery
per @Stefan : To answer the question of @ prime: If the thread is reused for another request and you do not clear the MDC between requests then you will access the values of the old request.Raddy

© 2022 - 2024 — McMap. All rights reserved.