Jetty Logo
Contact the core Jetty developers at www.webtide.com

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

Example: Capturing Multiple Logging frameworks with Slf4j

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:

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 APISlf4j Binding JarSlf4j Adapter JarUnderlying Logging Framework
Logback APIn/alogback-classic.jarlogback-core.jar
Log4jlog4j-over-slf4j.jarslf4j-log4j12.jarlog4j.jar
JDK 1.4 Loggingjul-to-slf4j.jarslf4j-jdk14.jar(Core Java Classlib)
Commons Loggingjcl-over-slf4j.jarslf4j-jcl.jarcommons-logging.jar

Logging API

The Logging API that you are either capturing events from and/or using to write out those events (eg: to disk)

Slf4j Binding Jar

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.

Slf4j Adapter Jar

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.

Underlying Logging Framework

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.

Note

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.

The Required JARs

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.

Any logging event from those APIs will now route down into Logback Classic to work with.

Configuring Server Classpath

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

Configuring Server Logging

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.

Initializing Jul-to-Slf4j Bridge

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>

Configuring Logback

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>

Note

When using the jul-to-slf4j Binding JAR, be sure you also utilize the LevelChangePropagator (as referenced in the SLF4JBridgeHandler javadoc.

Start Jetty

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 

Note

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!