We discuss here the major alternatives to JULI-to-SLF4J, and develop their advantages, complications, drawbacks or oddities.
If you are new to the many acronyms we use here, we provide you with a glossary below.
Some like “Manage logging with Logback and Apache Tomcat” bridge JUL to SLF4J so that you get a JULI(mini)→JUL→jul-to-slf4j→SLF4J setup. But this blog post above suffers from many issues.
-
Performance issues
It doesn't advise you to properly configure a LevelChangePropagator. Without it, the impact of the jul-to-slf4j bridge on performances can be outrageous.
Plus, the JULI(mini)→JUL step has performance issues (see the code excerpt in README).
-
Classpath issues
The given recipe avises you to add the logging jars to
lib/
and the System$CLASSPATH
. This results in having those libs duplicated on both System and Catalina classpath, which is unnecessary because of class loading delegation rules. Indeed, the parent System classpath always shadows the child Catalina's classpath. As a convention in Tomcat, the libs should actually be inbin/
in such cases where they are added to the System$CLASSPATH
customized insetenv.sh
. -
Config oddities
The described config uses
$CATALINA_HOME
all over the place where$CATALINA_BASE
is actually expected for a separate layout to work.Adding the
conf/logback
directory to the System classpath is a mixture of code & config that could definitely be misleading for Tomcat admins.
Some like Configuring Tomcat with Logback (FR) compose a JULI(JCL)→juli-adapters→log4j-over-slf4j→SLF4J setup. It builds on top of Using Log4j in Tomcat documentation, or the very similar Configuring log4j in tc-server documentation.
As a first step, the solution installs a full Jakarta Commons Logging (JCL) library that ships with Tomcat “extras”. JCL is known for being a complicated logging solution, as regards to the pretty scary (though interesting) classloader knownledge it requires.
As a second step, the solution relies on the multi-backend feature of JCL to
send the logs to the log4j-over-slf4j
facade, as if it were actually using
LOG4J.
What's notiecable in this second step, is that the log4j-over-slf4j
is
loaded with tha Catalina classloader. So what happens to the Tomcat logs that
might happen before the Catalina classloader is created? The response is that
they flow into a junk juli.YYYY-MM-DD.log
file.
You can deactivate the creation of this file with a LOGGING_CONFIG="-Dnop"
config in setenv.sh
, or deleting the conf/logging.properties
. Both ways
deactivate the default JULI logging. In which case the early logs that happen
in Tomcat before Catalina startup are always discard.
You may wonder why not using jcl-over-slf4j
in the 2nd step instead? We
actually discuss this alternative below.
Without any specific setup, just dropping the jcl-over-slf4j and SLF4J/Logback
jars into $CATALINA_BASE/lib/
, you can get very similar result as above,
without requiring tomcat-extras-juli-adapters
, and obtaining a canonical
JULI(JCL)→jcl-over-slf4j→SLF4J setup.
The observable difference is that the junk juli.YYYY-MM-DD.log
file contains
more logs that with the LOG4J setup above. Again, you can diable its creation
with the two ways described above, and chose to always discard those early
pre-Catalina logs.
The setup above can be further improved, adding jcl-over-slf4j and
SLF4J/Logback jars directly to $CATALINA_BASE/bin/
and the System
$CLASSPATH
. This is exactly what we do in juli-jcl-over-slf4j.
Then tomcat-slf4j-logback just goes further in that direction as discussed below.
On the other hand, our solution tries to support as many use cases as the very
complete tomcat-slf4j-logback,
which builds JULI/jcl-over-slf4j→SLF4J integration. But tomcat-slf4j-logback
implies a high deal of surgery made to JULI, in order to merge the thin
jcl-over-slf4j
into it, and just keep what's necessary. The result is
correct, but needs to rebuild the tomcat-juli.jar
every time you upgrade
Tomcat. And this cannot be done with tc-server
without loosing the JXM capabilities that the Pivotal guys have added into the
tomcat-juli.jar
that they ship.
-
JULI(mini) is the default logging system in Tomcat, that ships in
$CATALINA_HOME/bin/tomcat-juli.jar
. See: org.apache.tomcat:tomcat-juli in Maven Central. -
JULI(JCL) is the full Jakarta Commons Logging (JCL) implementation that is distributed with Tomcat “extras” (in
$CATALINA_HOME/bin/extras/tomcat-juli.jar
) as an optional drop-in replacement for JULI(mini) for extended features. See org.apache.tomcat.extras:tomcat-extras-juli in Maven Central. -
JUL is the
java.util.logging
framework that ships with Java implementations by default. -
LOG4J (LOGging for Java) was a very popular logging system, because at the time it brought better performance compared to JUL. This was until SLF4J & Logback came out. Now LOG4J 2.0 tries to come back in competition. But SLF4J has become a standard.
-
SLF4J (Simple Logging Facade for Java) and Logback (LOGging BACKend) started as a rewrite of LOG4J and brought separation of concerns and multi-backend à la JCL, but without going into the multi-class-loaders (complicated) use cases.
-
jul-to-slf4j is a bridge library that provides a JUL appender to use in your config so that the logs that flow through JUL loggers then go into SLF4J loggers and appenders.
-
log4j-over-slf4j is a bridge library that provides a LOG4J facade with LOG4J loggers that actually are SLF4J loggers behind the scene.
-
jcl-over-slf4j is a more elaborated adapter library that leverages the multi-backend design of JCL. It provides a JCL implementation that sends JCL logs into the SLF4J system.