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
The term "Centralized Logging" refers to a forced logging configuration for the Jetty Server and all Web Applications that are deployed on the server. Routing all logging events from even the Web Applications down to a single configuration on the Server side.
The example below will present how to accomplish this with Jetty and Slf4j, using Logback to manage the final writing of logs to disk.
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.
Provides a custom Deployment Lifecycle Binding to force Web Applications to use Server side logging implementations. See github.com/jetty-project/jetty-webapp-logging for source.
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 7 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 6221 Mar 12 16:21 jetty-webapp-logging-9.0.0.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)
# Force Server side Logging APIs etc/jetty-webapp-logging.xml # Enable jul-to-slf4j layer etc/jetty-jul-to-slf4j.xml # Adding lib/logging to server classpath OPTIONS=logging
Now verify that the 7 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: 9.0.0 | ${jetty.home}/lib/logging/jetty-webapp-logging-9.0.0.jar 20: 1.6.6 | ${jetty.home}/lib/logging/jul-to-slf4j-1.6.6.jar 21: 1.6.6 | ${jetty.home}/lib/logging/log4j-over-slf4j-1.6.6.jar 22: 1.0.7 | ${jetty.home}/lib/logging/logback-classic-1.0.7.jar 23: 1.0.7 | ${jetty.home}/lib/logging/logback-core-1.0.7.jar 24: 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.
In order to force all deployed Web Applications to use the Server side implementations for the various Logging APIs, we will utilize a custom Deployment Lifecycle Binding to configure the Web Application Classloader appropriately.
A custom Deployment Lifecycle Binding for this precise purpose is
provided as part of the
jetty-webapp-logging.jar
.
The implementation for the CentralizedWebAppLoggingBinding
class found in the jetty-webapp-logging.jar
.
package org.eclipse.jetty.webapp.logging; import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.AppLifeCycle; import org.eclipse.jetty.deploy.graph.Node; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.webapp.WebAppContext; public class CentralizedWebAppLoggingBinding implements AppLifeCycle.Binding { public String[] getBindingTargets() { return new String[] { "deploying" }; } public void processBinding(Node node, App app) throws Exception { ContextHandler handler = app.getContextHandler(); if (handler == null) { throw new NullPointerException("No Handler created for App: " + app); } if (handler instanceof WebAppContext) { WebAppContext webapp = (WebAppContext)handler; webapp.addSystemClass("org.apache.log4j."); webapp.addSystemClass("org.slf4j."); webapp.addSystemClass("org.apache.commons.logging."); } } }
In
order for Jetty's DeploymentManager to utilize this class, we'll need
create the etc/jetty-webapp-logging.xml
file (the same one that is referenced above in the
start.ini
)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd"> <!-- =============================================================== --> <!-- Enable Centralized Logging in the Jetty Server --> <!-- =============================================================== --> <Configure id="Server" class="org.eclipse.jetty.server.Server"> <Ref refid="DeploymentManager"> <Call name="addLifeCycleBinding"> <Arg> <New class="org.eclipse.jetty.webapp.logging.CentralizedWebAppLoggingBinding"> </New> </Arg> </Call> </Ref> </Configure>
The configuration of the start.ini above will use this xml file.
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.
Before you start Jetty, lets verify that our start.ini is correctly setup.
Run the following command and check the last section of the output. It should contain the highlighted entries.
[jetty-distribution-9.0.0.v20130308]$ java -jar start.jar --help ... The current start.ini arguments are: OPTIONS=Server,websocket,resources,ext etc/jetty.xml OPTIONS=client etc/test-realm.xml OPTIONS=jmx etc/jetty-jmx.xml OPTIONS=jsp etc/jetty-http.xml etc/jetty-deploy.xml etc/jetty-requestlog.xml etc/jetty-webapp-logging.xml etc/jetty-jul-to-slf4j.xml OPTIONS=logging
You are done.
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!