Using MDC in JBoss AS 6 applications

JBoss logging, like Apache log4j can make use of an MDC (Mapped Diagnostic Context) for logging information specific to a thread and its children.

The JavaDoc for Log4J's MDC can be found here, JBoss logging MDC behaves in exactly the same way:http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/MDC.html

To use the MDC in your code you have to import org.jboss.logging.MDC, then use the static methods "put" and "remove" to populate entries in the MDC. The example code below shows a simple servlet which performs the following actions when browsed to:

  1. Writes a log entry without the MDC being populated
  2. Populates the MDC with two fields
  3. Writes another log entry
  4. Spawn and run a thread which writes another log entry
  5. Remove the fields from the MDC
  6. Write another log entry

TestServlet.java - set the MDC entries and spawn a child thread

package com.test;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.logging.MDC;
import org.jboss.mx.util.MBeanServerLocator;
import org.jboss.resource.work.JBossWorkManagerMBean;
import javax.management.MBeanServer;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectName;
import javax.resource.spi.work.WorkManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class TestServlet extends HttpServlet {

    private static final Log log = LogFactory.getLog(TestServlet.class);

    @Override
    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response) throws ServletException, IOException {
        doAction(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request,
                          HttpServletResponse response) throws ServletException, IOException {
        doAction(request, response);
    }

    protected void doAction(HttpServletRequest request,
                            HttpServletResponse response) throws ServletException, IOException {

        //1 first log without any MDC entries
        log.info("Log without MDC");

        //2 now add the MDC entries
        MDC.put("entry1", "some stuff");
        MDC.put("entry2", "some other stuff");

        //3 print a log line now the MDC has been populated
        log.info("Log with MDC");

        //4 use the work manager to spawn a child thread
        try {

            //get the work manager
            MBeanServer server = MBeanServerLocator.locateJBoss();
            ObjectName objectName = new ObjectName("jboss.jca:service=WorkManager");
            JBossWorkManagerMBean jwm = (JBossWorkManagerMBean)
                    MBeanServerInvocationHandler.newProxyInstance(server, objectName, JBossWorkManagerMBean.class, false);
            WorkManager wm = jwm.getInstance();

            //start the thread
            wm.doWork(new WorkImpl());

        }
        catch (Exception e) {
            log.error("Exception caught", e);
        }

        //5 remove the entries from the MDC
        MDC.remove("entry1");
        MDC.remove("entry2");

        //6 write another log line
        log.info("Another log without MDC");

     }
}

WorkImpl.java - write another log entry

package com.test;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.resource.spi.work.Work;
import java.io.Serializable;

public class WorkImpl implements Work, Serializable {
    private static final Log log = LogFactory.getLog(WorkImpl.class);

    @Override
    public void release() {

    }

    @Override
    public void run() {
        log.info("Child thread with MDC");
    }
}

Note: If the MDC entries are removed before the thread does its work then they will not be displayed in the child thread's log entries

In order to display the MDC entries in the log you will have to configure an appender in the jboss-logging.xml with a pattern layout which will display the MDC entries in its output.

The sample below is taken from the default jboss-logging.xml, the important bit of configuration is the pattern-formatter, note in the example below the "%X{entry1}" and "%X{entry2}" elements in the pattern, which correspond to the MDC elements in the TestServlet.java code above.

<periodic-rotating-file-handler  
         file-name="${jboss.server.log.dir}/server.log"  
         name="FILE"  
         autoflush="true"  
         append="true"  
         suffix=".yyyy-MM-dd">  
      <error-manager>  
         <only-once/>  
      </error-manager>
       <formatter>  
         <pattern-formatter pattern="%d %-5p [%c] (%t) [%X{entry1}, %X{entry2}] %s%E%n"/>  
      </formatter>  
   </periodic-rotating-file-handler>  

When browsing to the servlet the following log entries are output:

2011-02-15 16:55:01,048 INFO  [com.test.TestServlet] (http-127.0.0.1-8080-2) [, ] Log without MDC
2011-02-15 16:55:01,049 INFO  [com.test.TestServlet] (http-127.0.0.1-8080-2) [some stuff, some other stuff] Log with MDC
2011-02-15 16:55:01,050 INFO  [com.test.WorkImpl] (pool-1-thread-16) [some stuff, some other stuff] Child thread with MDC
2011-02-15 16:55:01,050 INFO  [com.test.TestServlet] (http-127.0.0.1-8080-2) [, ] Another log without MDC

Known Issue : https://issues.jboss.org/browse/JBLOGGING-54

Discussion : https://community.jboss.org/thread/161799

posted @ 2014-09-13 16:37  princessd8251  阅读(251)  评论(0)    收藏  举报