I would like to intercept Jersey's logging with Logback, but I'm not sure how. Could somebody please give some pointers?
-
Are you using slf4j? Is it jersey on the client side or on the server side within an application server? – assylias Oct 08 '14 at 11:04
-
2I did this with jetty the other day using logback/slf4j. Dropping in the slfj bridging jars fro JUL, commons logging and log4j means you'll catch almost everything and can configure it from one logback config file. – tom Oct 08 '14 at 11:11
-
@assylias: It's both on the client and server side. – carlspring Oct 08 '14 at 11:17
-
On the client side you can use a bridge or if you don't mind a little hack: http://stackoverflow.com/a/26103488/829571 – assylias Oct 08 '14 at 11:20
-
2jersey uses java util logging. put the jul-to-sl4fj bridge on your classpath. See http://www.slf4j.org/legacy.html#jul-to-slf4j – Nathanael Oct 10 '14 at 15:13
1 Answers
Jersey logs to java.utils
logging (JUL). You can redirect JUL logging to SLF4J with the jul-to-slf4j bridge. To achieve this, add org.slf4j:jul-to-slf4j
as a dependency to your project. If you use Maven:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
To initialize the bridge, invoke SLF4JBridgeHandler.install()
during the initialization of your application.
This will however not remove any handlers from JUL's root logger, typically resulting in duplicated log output (since JUL still produces output). To remove the JUL handlers invoke SLF4JBridgeHandler.removeHandlersForRootLogger()
.
These invocations can for example be done in the application's main method or a static initializer block of your main class.
static {
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
}
The bridge will only receive logs that the JUL loggers actually process (based on log level). To give Logback full control over log selection we need to make sure all log levels are processed by JUL, so that all logs reach the Logback loggers. This is done by setting the JUL loggers to the lowest possible log level:
static {
java.util.logging.LogManager.getLogManager().reset();
java.util.logging.Logger.getLogger("global").setLevel(Level.FINEST);
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
}
This does mean that all logs will be processed by the JUL loggers and the bridge, leading to a considerable performance hit. Logback has a solution for this: by adding the LevelChangePropagator
context listener, Logback's log levels will be propagated to JUL's loggers. LevelChangePropagator
can also perform the reset of JUL's log manager from the previous code block. To configure all this, add the following to your logback.xml
:
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
With this configuration you can go for the first initialization block in this answer, since the first two statements of the second block are now handled by the context listener. To be precise, there's actually a small difference: the LogManager.reset()
method resets all log levels and removes all handlers except from the root logger, while the "resetJUL" option on the context listener only resets the log levels.
To summarize:
- add
jul-to-slf4j
dependency - add initialization code (the first variant from this answer)
- add
LevelChangePropagator
context listener to your Logback configuration

- 6,095
- 4
- 38
- 55