A simple guide to Tomcat logging

In a production Tomcat environment, effective use of logging is an important part of administrating your site and keeping track of your Tomcat server's performance.

You probably already have implemented logging in your web applications, and may not see why you should worry about configuring loggers for Tomcat's internals.  This is understandable - Tomcat's default logging configuration is fine for most users.  However, spending some time familiarizing yourself with the logging options available in Tomcat can save you valuable time if you find yourself dealing with an unexpected issue.  

Here's a rundown of the most common Tomcat logging frameworks, configurations, and concerns, to help you get started on adding a functional logging system to your administrative toolkit today.

Tip: Logging, diagnostics, error-free deployment, and advanced application provisioning can be done for your entire Tomcat infrastructure all in one console. Try Tcat today!

An overview of Tomcat logging

As of Tomcat 5.5, Apache's Java Commons Logging (JCL) technology is used throughout Tomcat.  JCL is a lightweight API for Java applications that allows hierarchical logging to be supported across all log levels, independent of logging implementation.  This means that rather being limited to a specific hard-coded framework, you can choose the solution that works for you with only a small amount of extra configuration.  

In this article, we'll focus on the two most common logging implementations used for Tomcat - the included JULI implementation, and Log4J, a popular, feature-rich implementation compatible with JCL.


Meet JULI - Java utility logging implementation

Although all JDKs ship with logging functionality provided by java.util.logging, this default implementation is not designed for container-based environments.  To get around this limitation, Tomcat replaces the default LogManager with JULI, a modified implementation with a number of additional features for handling containers.

The most notable of JULI's extended functionalities is the ability to set property files on a per-classloader basis.  This feature makes redeployment of web applications significantly less labor-intensive.  

Configuring JULI

Here's a look at all the layers at which JULI's logging can be configured, including both layers standard to java.util.logging and JULI's per-classloader layers:

  • logging.properties, located in your JDK's $JAVA_HOME/jre/lib directory, or at a custom location defined by editing the java.util.logging.config.file property.
  • java.util.logging.config.class, which is used for programmatic configuration
  • a logging.properties file located within each classloader you wish to configure.  This allows you to create separate configurations for each of your web applications with lifecycles equivalent to the given application, in addition to your core Tomcat logging configuration.  

JULI uses similar configuration syntax to that used by java.util.logging, with some additional functionality to integrate more flexibly into Tomcat's container-based environment.  Very detailed documentation on the default java.util.logging configuration syntax is available on Sun's J2SE site, but here's an overview of JULI's additional features:

  • To allow multiple handlers of a single class to be defined, handler prefixes consisting of a strings starting with a digit and ending with a "." (e.g. "1example.") are supported.
  • A list of a logger's handlers can be defined using the property loggerName.handlers, a functionality you might recognize from Java 6.x.
  • The loggerName.useParentHandlers boolean value dictates whether or not loggers delegate to a parent with associated handlers.  By default, this feature is disabled.
  • The .handlers property can be used to define the root loggers handler set.
  • Logger buffering can be configured on a per-handler basis using the bufferSize property.  Values great than 0 will cause the handler to use a BufferedOutputStream of equal value, in addition to system default buffering, while setting the value to 0 will use only the system default value.  Setting a value less than zero will cause the buffer to flush on every write to the log, effectively disabling buffering.
  • Setting a property value to ${systemPropertyName} will cause the property value to be replaced by the specified system property.

Simple examples of the logging.properties file for both Tomcat's core and per-web application configurations are provided on Apache's Tomcat Documentation site.


Using Log4J with Tomcat

Log4J is far and away the most popular logging implementation for Java web applications, for good reason - it's speed-optimized, hierarchical, fail-stop, thread-safe, highly configurable and extensible, and specifically designed to mitigate the performance hit caused by log statements, without removing them.  

In other words, even though Tomcat is configured to use JULI logging out of the box, if you're at all interested in building a more elegant logging system for your site, you should consider switching to Log4J.  Here's a basic guide to getting Log4J up and running on Tomcat.

Configuring Log4J

Thanks to Tomcat's JCL support, configuring Log4J for the first time is a fairly painless process.  However, before you get started, you'll have to download replace Tomcat's included JCL support, which is hard-coded for use with JULI, with a full version of JCL.  

You can either download the full JCL implementation from the "bin/extras" directory of the Apache Tomcat download page, or build it from the Tomcat source tree, using the command -f extras.xml, which will generate "tomcat-juli.jar" and "tomcat-juli-adapters.jar" in Tomcat's "output/extras" directory.  Copy these files to "$CATALINA_HOME/bin/" (replacing the existing "tomcat-juli.jar"), and your Tomcat will have full JCL support.

Now that Tomcat is ready to work with Log4J, download the logger from the project website, and place "log4jx.y.z.jar" in "$CATALINA_HOME/lib".

Just two more steps to go.  Since you won't be using logging.properties for configuration anymore, you'll have to create log4j.properties in "$CATALINA_HOME/lib".  Eventually, you'll want to modify this file to take advantage of the many features Log4J will make available to you, but for now you can just use the basic configuration recommended by Apache.  This will generate "tomcat.log" in your main Tomcat logs folder, with a 10MB maximum size and a maximum of 10 backups:

  log4j.rootLogger=INFO, R 






  log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n

That's it!  Restart Tomcat, and your new Log4J system will be ready to go.  

Container-Specific naming

You can explore your new options with Log4J in depth on the project website, but here's one very useful feature that you should not neglect: package-specific logging.  Log4J uses Engine and Host names enclosed in square brackets to allow very specific levels of logging for different components.  Here's an example of this syntax in action provided in the Apache Tomcat documentation:




Here's an example of using Log4J to log JSP servlets running on a specific Tomcat server at the lowest threshold:

org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/].[jsp] = ALL

You can also use this syntax and configuration layout on a per-application basis by including a custom "log4j.properties" in "WEB-INF/classes" and copying log4jx.y.z.jar to "WEB-INF/lib".

A final word of warning: when configuring Log4J, you should be aware that low threshold settings such as DEBUG or ALL are extremely verbose, and will noticeably slow Tomcat's startup time.