(home | about | stats)

pwyky: TomcatLogging

With the introduction of Tomcat 5, the Tomcat team switched from using Log4j for the default logging mechanism to the new Jakarta Commons Logging package. The goal of the commons logging project is to provide a layer of abstraction between a web application and the logging implementation, which is a good thing. I just need to figure out the various ways to use and configure it.

The other reason for this page is my own experience. I added log4j.jar to one of my web apps and got a cryptic error followed by no logging whatsoever. I finally figured out at least how to control logging a little better. Hope this helps. Commons Logging Introduction

The simplest commons logging example is really simple. Be sure to use JDK 1.4. Make sure commons-logging.jar is somewhere in your classpath (I put it in WEB-INF/lib, you can put it in common/lib, whatever) and add the following servlet to your web app. Make sure log4j.jar is not in your common/lib or web app WEB-INF/lib directories yet.

/*
 * Logging in Tomcat 5
 *
 */
package com.mobilitytech.sandbox.logging;

import org.apache.commons.logging.*;
import javax.servlet.http.*;

public class LogServlet extends HttpServlet {
	private static Log log = LogFactory.getLog(LogServlet.class);

	public void doGet(HttpServletRequest request,
					  HttpServletResponse response) {
		log.info("doGet");
	}
}

The one thing you have to do to use the commons logging facility is use the LogFactory class to get an instance of a class that implements org.apache.commons.logging.Log. Above we're passing the class to the log factory, which will prepend the class name to all log output. Then you can call a method on the log object that corresponds to the message severity (debug, info, warn, error, fatal) to write a message to the log. Debug Logging and the JDK 1.4 Log Implementation

How do you turn on debug level logging for the JDK 1.4 logging implementation? You'd be much better off using info level messages. Let me explain.

With the JDK logger found in java.util.logging since 1.4, there is no DEBUG level. The more detailed levels are INFO, CONFIG, FINE, FINER and FINEST. The JDK 1.4 commons logging implementation logs at the FINE level. The problem is this also contains VM trace messages, which means along with your Tomcat logging output you'll get a lot of VM output.

If you really really want to do this, you'll need to change logging.properties in your $JAVA_HOME/jre/lib directory (to figure out what Tomcat is running if you're running a Windows service or something else, just do log.info(System.getProperty("java.home"));. You'll see a couple instances of INFO in the properties file. Change them to FINE. Don't say I didn't warn you. Commons Logging Implementations

Before we go too much farther, add this to your servlet:

if (log instanceof Jdk14Logger)
    log.info("JDK14");
else if (log instanceof Log4JLogger)
    log.info("Log4J");
else if (log instanceof SimpleLog)
    log.info("SimpleLog");

This will log the name of the logging implementation you're currently using.

Now copy log4j.jar into your web app's lib directory. Tomcat should log something along the lines of "Additional JARs have been added" and reload the web app. Hit your servlet again. You'll see an error in the logs like this:

log4j:WARN No appenders could be found for logger (com.mobilitytech.logging.LogServlet)
log4j:WARN Please initialize the log4j system properly.

You won't see any more logging from your web app after you add log4j.jar. Why is this? Simple. The commons logging system uses the following steps (in order) to figure out what logging implementation to use (paraphrased from the Commons Logging User Guide):

Since we didn't have Log4J in our class path before, the log factory was figuring out we were running on a 1.4 VM and using the Java 1.4 java.util.logging classes. After we added log4j.jar to our web app, our servlet got reloaded and used LogFactory to create a new Log object. LogFactory found Log4J in our class path, so now we have to configure it. Configuring Log4J

Add a file called "log4j.properties" in your WEB-INF/classes directory (the file has to be somewhere in your web app's class path) with these contents:

# Set root logger level to INFO and its only appender to A1.
log4j.rootLogger=INFO, A1

# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

Don't use debug right off the bat. Here's why. This configuration file sets up one Log4J logger that will get used for all commons logging in your application server. Set the level to debug and you'll see all the debug logging for Tomcat. Yikes.

To limit debugging output to only your classes, add a line like this:

log4j.logger.com.mobilitytech=DEBUG

All packages starting with "com.mobilitytech" will have debug logging turned on.

www.mobilitytech.com owner. This is a pwyky site.