10

I'm trying to configure Tomcat 8 to use Log4j2 for logging.

I've found this reference for Logging in Tomcat using Log4j. It provides a sample log4j.properties file that configures Log4j to match Tomcat's internal logging. Most of this looks pretty straightforward to convert for Log4j2, but the section at the end that maps loggers to appenders has me stumped:

# Configure which loggers log to which appenders
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost] = INFO, LOCALHOST
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager] =\
  INFO, MANAGER
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager] =\
  INFO, HOST-MANAGER

Has anyone converted this configuration to work with Log4j2? I've been working from the Log4j2 configuration documentation and have read through the Log4j2 Architecture page, but I haven't found much material on how to do this sort of container mapping in Log4j2.

I suppose I could do a separate configuration for each container, but I'd prefer to keep it in one place, as in the sample Log4j configuration.

David Kellerman
  • 271
  • 1
  • 2
  • 9
  • Have you tried asking on the tomcat-users mailing list? http://tomcat.apache.org/lists.html That's where the experts hang out and you're most likely to get an accurate response. – Remko Popma Dec 31 '14 at 00:46
  • Likely your only chance of using log4j2 with tomcat will be to use the log4j 1.x bridge. http://logging.apache.org/log4j/2.0/manual/migration.html – Brett Okken Jan 02 '15 at 04:49
  • @Brett Okken this is no longer true in 8.5.11 +. extras for july was terminated since 8.5.11 and only thing you need to use log4j2 is to use David Kellerman script and 3 jars from log4j2 (core,api,july) (plus configfile) – jareeq Mar 10 '17 at 11:36

3 Answers3

17

After asking this question, I spent some more time with setting up log4j2, and this is the log4j2.xml file I came up with. It mimics the configuration described in Logging in Tomcat using Log4j. It uses multiple loggers to route messages to separate log files.

<?xml version="1.0" encoding="utf-8"?>
<Configuration status="info">
  <Properties>
    <Property name="logdir">${sys:catalina.base}/logs</Property>
    <Property name="layout">%d [%t] %-5p %c- %m%n</Property>
  </Properties>
  <Appenders>
    <Console name="CONSOLE" target="SYSTEM_OUT">
      <PatternLayout pattern="${layout}"/>
    </Console>
    <RollingFile name="CATALINA"
        fileName="${logdir}/catalina.log"
        filePattern="${logdir}/catalina.%d{yyyy-MM-dd}-%i.log">
      <PatternLayout pattern="${layout}"/>
      <Policies>
        <TimeBasedTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="1 MB"/>
      </Policies>
      <DefaultRolloverStrategy max="10"/>
    </RollingFile>
    <RollingFile name="LOCALHOST"
        fileName="${logdir}/localhost.log"
        filePattern="${logdir}/localhost.%d{yyyy-MM-dd}-%i.log">
      <PatternLayout pattern="${layout}"/>
      <Policies>
        <TimeBasedTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="1 MB"/>
      </Policies>
      <DefaultRolloverStrategy max="10"/>
    </RollingFile>
    <RollingFile name="MANAGER"
        fileName="${logdir}/manager.log"
        filePattern="${logdir}/manager.%d{yyyy-MM-dd}-%i.log">
      <PatternLayout pattern="${layout}"/>
      <Policies>
        <TimeBasedTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="1 MB"/>
      </Policies>
      <DefaultRolloverStrategy max="10"/>
    </RollingFile>
    <RollingFile name="HOST-MANAGER"
        fileName="${logdir}/host-manager.log"
        filePattern="${logdir}/host-manager.%d{yyyy-MM-dd}-%i.log">
      <PatternLayout pattern="${layout}"/>
      <Policies>
        <TimeBasedTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="1 MB"/>
      </Policies>
      <DefaultRolloverStrategy max="10"/>
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="info">
      <AppenderRef ref="CATALINA"/>
    </Root>
    <Logger name="org.apache.catalina.core.ContainerBase.[Catalina].[localhost]"
        level="info" additivity="false">
      <AppenderRef ref="LOCALHOST"/>
    </Logger>
    <Logger name="org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager]"
        level="info" additivity="false">
      <AppenderRef ref="MANAGER"/>
    </Logger>
    <Logger name="org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager]"
        level="info" additivity="false">
      <AppenderRef ref="HOST-MANAGER"/>
    </Logger>
  </Loggers>
</Configuration>

However, getting this to work properly required getting a bunch of other files configured correctly. The tomcat 7 internal logging with log4j2.xml posting from Paramita Banerjee was helpful with this.

This file goes in CATALINA_HOME/bin/:

  • tomcat-juli.jar

If you're pulling this from the Maven repository, you'll get a file named something like tomcat-extras-juli-8.0.15.jar (the current version when I wrote this). However, it needs to be renamed to tomcat-juli.jar – the Tomcat setup scripts use that name in setting up the CLASSPATH.

These files go in CATALINA_HOME/lib/:

  • commons-logging-1.2.jar
  • log4j-1.2-api-2.1.jar
  • log4j-api-2.1.jar
  • log4j-core-2.1.jar
  • log4j-jcl-2.1.jar
  • log4j-jul-2.1.jar
  • log4j-web-2.1.jar
  • tomcat-juli-adapters-8.0.15.jar

log4j-web-2.1.jar may not be needed here (it may just need to be deployed with your web application) – its use is described in Using Log4j 2 in Web Applications. log4j-1.2-api-2.1.jar is needed only if you have applications that use the older log4j 1.2 interface.

In CATALINA_BASE/conf, I disabled logging.properties.

I used the following setenv.sh script to define the CLASSPATH and LOGGING_MANAGER environment variables correctly for Tomcat. It goes in either CATALINA_BASE/bin or into CATALINA_HOME/bin. (I put it in CATALINA_HOME/bin.) It is executed by Tomcat's startup scripts if it's present. You might prefer something simpler, but this is in keeping with the style of the startup scripts.

LOG4J_JARS="log4j-core-2.1.jar log4j-api-2.1.jar log4j-jul-2.1.jar"

# make log4j2.xml available
if [ ! -z "$CLASSPATH" ] ; then CLASSPATH="$CLASSPATH": ; fi
CLASSPATH="$CLASSPATH""$CATALINA_BASE"/lib

# Add log4j2 jar files to CLASSPATH
for jar in $LOG4J_JARS ; do
  if [ -r "$CATALINA_HOME"/lib/"$jar" ] ; then
    CLASSPATH="$CLASSPATH":"$CATALINA_HOME"/lib/"$jar"
  else
    echo "Cannot find $CATALINA_HOME/lib/$jar"
    echo "This file is needed to properly configure log4j2 for this program"
    exit 1
  fi
done

# use the logging manager from log4j-jul
LOGGING_MANAGER="-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager"

As Nick mentioned in his response, there's also the output to the access log. I haven't tried to do anything with that, either.

I hope others find this useful. In retrospect, it seems pretty straightforward. However, there are a lot of parts that have to be “just right” for it to work, and that was a challenge (at least for a newbie).

Community
  • 1
  • 1
David Kellerman
  • 271
  • 1
  • 2
  • 9
  • 1
    Your log4j2.xml file was spot on, but a lot of your configuration is superfluous. I used the steps here instead: http://stackoverflow.com/a/35618384/399105 – bmaupin Nov 04 '16 at 19:58
  • I made a few adjustments for my own needs, such as only doing time based rolling (and not size based) and compressing logs by default: https://gist.github.com/bmaupin/475a0cd6e8b374d876f5085846761fb6 – bmaupin Nov 08 '16 at 14:21
  • 1
    thanks for sharing this solution - got log4j2 2.8.1 working on tomcat 9 – Matt Sloan Mar 09 '17 at 17:14
  • 1
    since tomcat 8+ works without extras you need only log4j-core-2.8.1.jar, log4j-api-2.8.1.jar, log4j-jul-2.8.1.jar and log4j2.xml in lib. With above script inside setenv.sh to get things done - tested on 8.5.11 – jareeq Mar 10 '17 at 11:31
  • Where are the tomcat-juli and especially the tomcat-juli-adapters.jar for Tomcat 8.5 and above? I can't seem to find them – N4zroth Oct 22 '18 at 15:52
  • For Apache Tomcat 8.5 and later the dependencies are simplified. Check https://logging.apache.org/log4j/2.x/log4j-appserver/index.html – Drazen Nikolic Mar 10 '21 at 15:50
4

I followed the reference for Logging in Tomcat using Log4j and added tomcat-juli.jar to the bin dir and I also added tomcat-juli-adapters.jar to the lib dir. Afterwards i added the log4j-api-2.1.jar, log4j-core-2.1.jar and log4j-1.2-api-2.1.jar to the lib dir.

After that I added log4j2.xml to the lib dir. I kept the configuration fairly simple using a time and size based rolling configuration that zips the archived logs:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="catalina" packages="">

    <Appenders>
        <RollingRandomAccessFile name="catalina"
            fileName="${sys:catalina.base}/logs/catalina.log"
            filePattern="${sys:catalina.base}/logs/catalina/$${date:yyyy-MM}/catalina-%d{yyyy-MM-dd}-%i.log.zip">
            <PatternLayout>
                <Pattern>%d{MMM d, yyyy HH:mm:ss}: %5p (%F:%L) - %m%n</Pattern>
            </PatternLayout>
            <Policies>
                <TimeBasedTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="250 MB" />
            </Policies>
            <DefaultRolloverStrategy max="100" />
        </RollingRandomAccessFile>
    </Appenders>
    <Loggers>
        <!-- default loglevel for emaxx code -->
        <logger name="org.apache.catalina" level="info">
            <appender-ref ref="catalina" />
        </logger>
        <Root level="info">
            <appender-ref ref="catalina" />
        </Root>
    </Loggers>
</Configuration>

This way you'll get all logging in the catalina.log. I'm still working on getting the accessLog to do the same.
EDIT: I found this site. this way you can direct access logging to the catalina.log. (I couldn't get it to log to it's own appender)

I didn't worry about the logging for manager and host manager, since we don't have them in production environments, but they might just log to the catalina.log too. I haven't tested it.

This was tested on tomcat-7.0.42, it should work in tomcat8 too.

rjdkolb
  • 10,377
  • 11
  • 69
  • 89
Nick Hardy
  • 41
  • 3
0

For system properties you need to prefix variables with "sys:" it indicates System Properties

Example:

appender.file.fileName=${sys:catalina.base}/logs/XXX.log

for more information go through below link http://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution

G Ganesh
  • 1
  • 2