private support for your internal/customer projects ... custom extensions and distributions ... versioned snapshots for indefinite support ... scalability guidance for your apps and Ajax/Comet projects ... development services from 1 day to full product delivery
This page describes how to Configure Jetty for capturing multiple logging frameworks logging events into a single logging implementation handled by Slf4j.
When using Slf4j, it is possible to configure a single logging solution for the variety of logging libraries available in common use.
With some careful setup, you can support all of the following logging APIs at the same time, with a single configuration file to control the output of events produces by these APIs.
Logging APIs supported by Slf4j:
Slf4j API
Logback API
Apache Log4j 1.2
JDK 1.4 Logging (aka java.util.logging)
Apache Commons Logging
To accomplish this you must make some careful choices.
Starting with: What will my 1 single Underlying Logging Framework be?
This decision will guide the rest of your decisions on JAR choices.
The choice of underlying logging framework forces you to be careful about other logging JARs present on the Server Classpath.
Table 9.2. Slf4j Logging Grid
Logging API | Slf4j Binding Jar | Slf4j Adapter Jar | Underlying Logging Framework |
---|---|---|---|
Logback API | n/a | logback-classic.jar | logback-core.jar |
Log4j | log4j-over-slf4j.jar | slf4j-log4j12.jar | log4j.jar |
JDK 1.4 Logging | jul-to-slf4j.jar | slf4j-jdk14.jar | (Core Java Classlib) |
Commons Logging | jcl-over-slf4j.jar | slf4j-jcl.jar | commons-logging.jar |
The Logging API that you are either capturing events from and/or using to write out those events (eg: to disk)
These are special JARs, created and maintained by the Slf4j project that pretend to be the various Logging API implementation classes, but instead just route that Logging API's events to Slf4j to handle.
There MAY be multiple Slf4j Binding Jars present on the Classpath at the same time.
For a single Logging API, if you choose to use the Slf4j Binding Jar, then you MUST NOT include the SLf4j Adapter Jar or Underlying Logging Framework in the Classpath as well.
These JARs are created and maintained by the Slf4j project and route Slf4j logging events to a specific Underlying Logging Framework.
There MUST NOT be multiple Slf4j Adapter Jars present on the Classpath at the same time.
Logging events that these Adapter Jars capture can come from direct use of the Slf4j API or via one of the Slf4j Binding Jar implementations.
This is the last leg of your configuration, the implementation that processes, filters, and outputs the Logging events to the Console, logging directory on disk, or whatever else that the Underlying Logging Framework supports (like Socket, SMTP, Database, or even Syslog in the case of Logback)
There MUST NOT be multiple Underlying Logger Frameworks on the Classpath.
Some 3rd party libraries often provide their own implementations of common Logging APIs, be sure that you don't accidentally include a Underlying Logging Framework by accident.
An example would be if you are using SpringSource you will
likely have a
com.springsource.org.apache.log4j.jar
along
with a log4j.jar
, which have the same classes
in them. In this specific example, use the
com.springsource.org.apache.log4j.jar
version
and exclude the log4j.jar
, as the
SpringSource version includes extra metadata suitable for
SpringSource use.
For purposes of this document, we'll choose Logback as our Underlying Logging Framework.
This means that we have to now use logback-classic.jar and logback-core.jar, and ensure that we exclude any other Slf4j Adapter Jar or Underlying Logging Framework, as this will cause problems.
We also now need to include the other Slf4j Binding Jars in our Classpath, along with some special initialization for java.util.logging.
Lets get started.
There will be 3 JARs you will need to download
logback-classic-1.0.7.jar
This is the underlying logging framework and adaption layer for Slf4j
logback-core-1.0.7.jar
The common implementation classes for the Logback project.
log4j-over-slf4j-1.6.6.jar
The Slf4j Binding JAR for Log4j
jul-to-slf4j-1.6.6.jar
The Slf4j Binding JAR for java.util.logging
jcl-over-slf4j-1.6.6.jar
The Slf4j Binding JAR for Commons Logging
slf4j-api-1.6.6.jar
This is the basic Slf4j API that Jetty's Slf4jLog implementation uses.
This will allow to capture Logging events generated by any of the following APIs.
org.slf4j.Logger - Slf4j API
ch.qos.logback.classic.Logger - Logback API
org.apache.log4j.Logger - Apache Log4j API
java.util.logging.Logger - Core java.util.logging API
org.apache.commons.logging.Log - Apache Commons Logging API
Any logging event from those APIs will now route down into Logback Classic to work with.
In order for the Server to use these new JARs you will need to put them into place and tell Jetty to load them on each startup.
Create a ${jetty.home}/lib/logging/ directory and place the 6 files you downloaded there.
[jetty-distribution-9.0.0.v20130308]$ ls -l lib/logging/ total 632 -rw-rw-r-- 1 jetty jetty 17289 Mar 12 16:21 jcl-over-slf4j-1.6.6.jar -rw-rw-r-- 1 jetty jetty 4955 Mar 12 16:21 jul-to-slf4j-1.6.6.jar -rw-rw-r-- 1 jetty jetty 20647 Mar 12 16:21 log4j-over-slf4j-1.6.6.jar -rw-rw-r-- 1 jetty jetty 251679 Mar 12 16:21 logback-classic-1.0.7.jar -rw-rw-r-- 1 jetty jetty 364399 Mar 12 16:21 logback-core-1.0.7.jar -rw-rw-r-- 1 jetty jetty 26176 Mar 12 16:21 slf4j-api-1.6.6.jar
Next, we need to edit the
${jetty.home}/start.ini
to get jetty to load these
logging files into the Server classpath.
Edit the start.ini
and check for the following
entries. (Add them to the end if missing)
# Enable jul-to-slf4j layer etc/jetty-jul-to-slf4j.xml # Adding lib/logging to server classpath OPTIONS=logging
Now verify that the 6 jars will be loaded by server classpath
[jetty-distribution-9.0.0.v20130308]$ java -jar start.jar --version | grep logging Active Options: [Server, client, ext, jmx, jsp, logging, resources, websocket] 18: 1.6.6 | ${jetty.home}/lib/logging/jcl-over-slf4j-1.6.6.jar 19: 1.6.6 | ${jetty.home}/lib/logging/jul-to-slf4j-1.6.6.jar 20: 1.6.6 | ${jetty.home}/lib/logging/log4j-over-slf4j-1.6.6.jar 21: 1.0.7 | ${jetty.home}/lib/logging/logback-classic-1.0.7.jar 22: 1.0.7 | ${jetty.home}/lib/logging/logback-core-1.0.7.jar 23: 1.6.6 | ${jetty.home}/lib/logging/slf4j-api-1.6.6.jar
If you have a
${jetty.home}/resources/jetty-logging.properties
,
make sure it contains just the following
# Configure Jetty for SLf4j Logging org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.Slf4jLog
This will tell Jetty to use the Slf4jLog implementation for its internal Logging.
There is an extra requirement when using the jul-to-slf4j.jar that requires us to inform java.util.logging of the existence of the SLF4JBridgeHandler.
We'll satisfy this requirement with a new
etc/jetty-jul-to-slf4j.xml
file, lovingly included in
the start.ini
above.
<?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd"> <Configure id="Server" class="org.eclipse.jetty.server.Server"> <Call class="org.slf4j.bridge.SLF4JBridgeHandler" name="removeHandlersForRootLogger"/> <Call class="org.slf4j.bridge.SLF4JBridgeHandler" name="install"/> </Configure>
You'll need a
${jetty.home}/resources/logback.xml
file to define
what you want Logback to do. It will be automatically located and loaded
on Logging startup.
Example ${jetty.home}/resources/logback.xml
file
<?xml version="1.0" encoding="UTF-8"?> <!-- Example LOGBACK Configuration File http://logback.qos.ch/manual/configuration.html --> <configuration> <!-- address performance concern with jul-to-slf4j --> <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator"> <resetJUL>true</resetJUL> </contextListener> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>\${jetty.home}/logs/jetty.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>jetty_%d{yyyy-MM-dd}.log</fileNamePattern> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender> <root level="info"> <appender-ref ref="STDOUT" /> <appender-ref ref="FILE" /> </root> </configuration>
When using the jul-to-slf4j Binding JAR, be sure you also utilize the LevelChangePropagator (as referenced in the SLF4JBridgeHandler javadoc.
You are now done configuring Jetty for all logging APIs. Just start Jetty to start utilizing it.
[jetty-distribution-9.0.0.v20130308]$ java -jar start.jar
This configuration will capture all Server side logging events and route them to the console and logging file handled by Logback. If you also want to capture all of the Web Application logging events, be sure to read Example: Centralized Logging with Logback for details.
See an error or something missing? Contribute to this documentation at Github!