Thread name filter

You can use a filter to set the name of a thread as it handles a request. Useful things to put in the thread name are the name of the user, a token to identify the request and any other useful objects in the session, such as a selected purchase order.

Here's the code for the filter. You will need to adapt it to your code:

package com.---.filter;

import java.io.IOException;
import java.util.Date;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;

import com.---.domain.User;


public class ThreadNameFilter implements Filter
{
  /**
   * Log.
   */
  private static Logger LOGGER = Logger.getLogger("com.---.filter.ThreadNameFilter");
  private static long requestToken = 0;   // Just a number to tie the logs for one request together.
  private static final int jvm = (int)(Math.random() * 10000);   // If multiple JVMs per box, so this should allow us to differentiate between sessions in the 2 JVMs.
  
  private FilterConfig filterConfig;
  
  public void init(FilterConfig filterConfig)  throws ServletException
  {
    LOGGER.debug("init()");
    this.filterConfig = filterConfig;
  }
  
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
  {
    HttpServletRequest theRequest = (HttpServletRequest)request;
    HttpSession session = theRequest.getSession(false);

    String oldThreadName = Thread.currentThread().getName();

    try
    {
      try
      {
        // Change the thread name to add useful info.
        StringBuffer sb = new StringBuffer();
        if(session != null)
        {
          User user = (User)session.getAttribute(User.NAME);
          if(user == null)
          {
            sb.append("User[No user object]");
          }
          else
          {
            sb.append("UserID[");
            sb.append(user.getId());
            sb.append("] userName[");
            sb.append(user.getUserName());
            sb.append("] screenName[");
            sb.append(user.getScreenName());
            sb.append("] ");
          }
        }
        sb.append("JVM[");
        sb.append(jvm);
        sb.append("] RT[");
        synchronized(ThreadNameFilter.class)
        {
          requestToken++;
          sb.append(requestToken);
        }
        sb.append("]");

        // Add useful things from the session e.g. selected PO number.


        Thread.currentThread().setName(sb.toString());
      }
      finally
      {
        chain.doFilter(request, response);
      }
    }
    finally
    {
      // Reset the thread name to avoid confusion.
      Thread.currentThread().setName(oldThreadName);
    }
  }
  
  /**
   * 
   */
  public void destroy()
  {
  }
}

Add this to web.xml:

<!-- Filter to set the thread name. -->
<filter>
  <filter-name>threadNameFilter</filter-name>
  <filter-class>com.---.filter.ThreadNameFilter</filter-class>
</filter>

...

<filter-mapping>
  <filter-name>threadNameFilter</filter-name>
  <url-pattern>*</url-pattern>
</filter-mapping>

The request token (RT) just displays a single number which is the same for all logs from one request, so you can tie a single request together. You could add a session token to tie all the logs from one session togehter.