Wednesday, 8 December 2010

JBoss - separating application logs without using monolithic jboss-log4j.xml

A minor irritant we've discovered in implementing applications for Jboss AS is that that the logging configuration for applications has to go through their monolithic jboss-log4j.xml file.

So we've managed to find a work-around (after some investigation of the Jboss class loaders and some trial and error).  This technique has been confirmed for jboss-eap-4.3 and jboss-4.2.3.GA but will likely work for other versions.

If you want to have split application logs and have that log4j.xml based configuration separated out (e.g. Not have it all in the jboss-log4j.xml file) then you can do the following.

1.) Your WAR/EAR must contain log4j-1.2.16.jar. It must be 1.2.16 or later as earlier versions don't work.

2.) The class loading for that WAR or EAR must have its java2ParentDelegation=false. So for example the jboss-app.xml file will look something like this:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss-app PUBLIC
      "-//JBoss//DTD J2EE Application 1.4//EN"
      "http://www.jboss.org/j2ee/dtd/jboss-app_4_2.dtd">
<jboss-app>
  <loader-repository>${your domain}:archive=${your app name}.ear
    <loader-repository-config>java2ParentDelegation=false</loader-repository-config>
  </loader-repository>
</jboss-app>

Now this means that the WAR/EAR will use the log4j-1.2.16.jar for logging within its own classloader, i.e. It will not use Jboss's log4j.jar library (and therefore the jboss-log4j.xml won't be used).

3.) In the MANIFEST.MF file in your WAR/EAR archive you need to set a Class-Path: entry that shows the location (directory) where the log4j.xml file that you want to use will reside. For example if your EAR file is deployed in the deploy directory, your Class-Path reference might be something like this:

Class-Path: ../conf/log/${application name}/

4.) Your log4j.xml file should just be an ordinary one, with no references to any special jboss classes. However, it will have an appender with the specifc name for the log file for the application you want to log for, e.g.


  <appender name="${module.name}" class="org.apache.log4j.RollingFileAppender">
    <param name="File" value="${jboss.server.home.dir}/log/${module.name}.log"/>
    <param name="Threshold" value="INFO"/>
    <param name="Append" value="true"/>
    <param name="MaxFileSize" value="2MB"/>
    <param name="MaxBackupIndex" value="20"/>
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d{yyyyMMdd HH:mm:ss.SSS} %-5p [%t] %C{1}.%M(): %x %m%n"/>
    </layout>
  </appender>

5.) OPTIONAL: You can still have all of your logging also go to the shared central $JBOSS_HOME/${instance}/log/server.log file by adding the following to your log4j.xml file:


  <appender name="all" class="org.apache.log4j.RollingFileAppender">
    <param name="File" value="${jboss.server.home.dir}/log/server.log"/>
    <param name="Threshold" value="INFO"/>
    <param name="Append" value="true"/>
    <param name="MaxFileSize" value="2MB"/>
    <param name="MaxBackupIndex" value="20"/>
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d{yyyyMMdd HH:mm:ss.SSS} %-5p [%t] %C{1}.%M(): %x %m%n"/>
    </layout>
  </appender>

I've updated the Jboss community wiki with this information (thanks for pointing out the location Jaikiran!).