Logging in Apache Tomcat is implemented with the help of Apache Commons Logging library. That library is a thin wrapper above different logging frameworks. It provides Tomcat with the ability to log hierarchically across various log levels without the need to rely on a particular logging implementation.
Since Tomcat 6.0, Tomcat uses a private package-renamed implementation of Apache Commons Logging, to allow web applications to use their own independent copies of the original Apache Commons Logging library. In the default distribution this private copy of the library is simplified and hardcoded to use the java.util.loggingframework.
To configure Tomcat to use alternative logging frameworks for its internal logging, one has to replace the logging library with the one that is built with the full implementation. Such library is provided as an extras component. Instructions on how to configure Tomcat to use Log4j framework for its internal logging may be found below.
A web application running on Apache Tomcat can:
- Use system logging API, java.util.logging.
- Use the logging API provided by the Java Servlets specification,
javax.servlet.ServletContext.log(…)
- Use any logging framework of its choice.
The logging frameworks used by different web applications run independently of each other. See class loading for more details. The exception to this rule is java.util.logging, if it used directly or indirectly by your logging library. That is because it is loaded by the system and is shared across web applications.
Java logging API — java.util.logging
Apache Tomcat has its own implementation of several key elements of java.util.logging API. This implementation is called “JULI”. The key component there is a custom LogManager implementation, that is aware of different web applications running on Tomcat (and their different class loaders). It supports private per-application logging configurations. It is also notified by Tomcat when a web application is unloaded from memory, so that the references to its classes can be cleared, preventing memory leaks.
This java.util.logging implementation is enabled by providing certain system properties when starting Java. The Apache Tomcat startup scripts do this for you, but if you are using different tools to run Tomcat (such as jsvc, or running Tomcat from within an IDE), you should take care of them by yourself.
More details about java.util.logging may be found in the documentation for your JDK and on its Javadoc pages for the java.util.logging package.
More details about Tomcat JULI may be found below.
Servlets logging API
The calls to javax.servlet.ServletContext.log(…) to write log messages are handled by internal Tomcat logging. Such messages are logged to the category named
org.apache.catalina.core.ContainerBase.[${engine}].[${host}].[${context}]
This logging is performed according to the Tomcat logging configuration. You cannot overwrite it in a web application.
The Servlets logging API predates the java.util.logging API that is now provided by Java. As such, it does not offer you much options. E.g., you cannot control the log levels. It can be noted, though, that in Apache Tomcat implementation the calls to ServletContext.log(String) or GenericServlet.log(String) are logged at the INFO level. The calls to ServletContext.log(String, Throwable) or GenericServlet.log(String, Throwable) are logged at the ERROR level.
Console
When running Tomcat on unixes, the console output is usually redirected to the file named catalina.out. The name is configurable using an environment variable. Whatever is written toSystem.err/out will be caught into that file. That may include:
- Uncaught exceptions printed by java.lang.ThreadGroup.uncaughtException(..)
- Thread dumps, if you requested them via a system signal
When running as a service on Windows, the console output is also caught and redirected, but the file names are different.
The default logging configuration in Apache Tomcat writes the same messages to the console and to a log file. This is great when using Tomcat for development, but usually is not needed in production.
Old applications that still use System.out or System.err can be tricked by setting swallowOutput attribute on aContext. If the attribute is set to true, the calls to System.out/err during request processing will be intercepted, and their output will be fed to the logging subsystem using thejavax.servlet.ServletContext.log(…) calls.
Note, that the swallowOutput feature is actually a trick, and it has its limitations. It works only with direct calls to System.out/err, and only during request processing cycle. It may not work in other threads that might be created by the application. It cannot be used to intercept logging frameworks that themselves write to the system streams, as those start early and may obtain a direct reference to the streams before the redirection takes place.
- Access logging
Access logging is a related but different feature, which is implemented as a Valve. It uses self-contained logic to write its log files. The essential requirement for access logging is to handle a large continuous stream of data with low overhead, so it only uses Apache Commons Logging for its own debug messages. This implementation approach avoids additional overhead and potentially complex configuration.