JUL-to-Log4j bridge
The JUL-to-Log4j bridge provides components that allow application and library that use
java.util.logging.Logger
(JUL) to log to the Log4j API instead.
This chapter covers advanced usage scenarios of the JUL-to-Log4j bridge. For the installation procedure and basic configuration see Using JUL-to-Log4j section of our Installation guide. |
Configuration
Struggling with the logging API, implementation, and bridge concepts? Click for an introduction.
- Logging API
-
A logging API is an interface your code or your dependencies directly logs against. It is required at compile-time. It is implementation agnostic to ensure that your application can write logs, but is not tied to a specific logging implementation. Log4j API, SLF4J, JUL (Java Logging), JCL (Apache Commons Logging), JPL (Java Platform Logging) and JBoss Logging are major logging APIs.
- Logging implementation
-
A logging implementation is only required at runtime and can be changed without the need to recompile your software. Log4j Core, JUL (Java Logging), Logback are the most well-known logging implementations.
- Logging bridge
-
Logging implementations accept input from a single logging API of their preference; Log4j Core from Log4j API, Logback from SLF4J, etc. A logging bridge is a simple logging implementation of a logging API that forwards all messages to a foreign logging API. Logging bridges allow a logging implementation to accept input from other logging APIs that are not their primary logging API. For instance,
log4j-slf4j2-impl
bridges SLF4J calls to Log4 API and effectively enables Log4j Core to accept input from SLF4J.
To make things a little bit more tangible, consider the following visualization of a typical Log4j Core installation with bridges for an application:
@startuml frame "Compile time" { [Application] --> [Log4j API] : logs to [Log4j API] #Cyan [SLF4J] #Cyan [Library 1] --> [SLF4J] : logs to [Application] --> [Library 1] : uses [Application] --> [Library 2] : uses [Application] --> [Library 3] : uses } frame Runtime { [Log4j Core] <.. [Log4j API] : is implemented by [Log4j Core] <.. (log4j2.xml) : is provided to [Log4j Core] #LightGreen [JPL-to-Log4j] ..> [Log4j Core] : forwards to [JPL-to-Log4j] #Yellow [SLF4J-to-Log4j] ..> [Log4j Core] : forwards to [SLF4J-to-Log4j] #Yellow [JUL-to-Log4j] ..> [Log4j Core] : forwards to [JUL-to-Log4j] #Yellow frame JRE { [JPL] #Cyan [JUL] #Cyan } } [Library 2] --> [JUL] : logs to [Library 3] --> [JPL] : logs to [JPL] ..> [JPL-to-Log4j] : is implemented by [JUL] ..> [JUL-to-Log4j] : is implemented by [SLF4J] ..> [SLF4J-to-Log4j] : is implemented by legend top right | <#LightGreen> | Logging implementation | | <#Yellow> | Logging bridge | | <#Cyan> | Logging API | | <size:18><U+2192></size> | Compile-time usage | | <size:18><U+21E2></size> | Runtime usage | endlegend @enduml
The java.util.logging
logging API, available since JRE 1.4, shares many similarities with other logging API, such as SLF4J or Log4j API.
Similarly to other APIs, it allows users to change the underlying
LogManager
implementation, but unlike other APIs, it has two big limitations:
-
it is part of JRE, which means that each JVM can contain only one instance of the
LogManager
class and all the applications of an application server must use the sameLogManager
implementation, -
it does not support auto-detection of the logging backend through
ServiceLoader
or a similar mechanim (see JDK-8262741 ). In order to switch to an alternateLogManager
implementation you must be able to set thejava.util.logging.manager
system property before the first logging call.
To work around the limitations of JUL, the JUL-to-Log4j bridge offers two installation options:
-
If you are able to modify the
java.util.logging.manager
system property very early in the JVM startup process, you can replace the defaultLogManager
implementation with a Log4j-specific one. This option gives the best performance. See UsingLogManager
for details. -
If JUL initializes before your application does, which is a typical behavior in application servers, you can still configure JUL to use Log4j as appender. See Using
Log4jBridgeHandler
for details.
Using LogManager
The best way to install the JUL-to-Log4j bridge on your system is to set the value of the java.util.logging.manager
Java system property to
org.apache.logging.log4j.jul.LogManager
This property must be set very early in an application initialization process, e.g. using the -D<property>=<value>
command line option of the java
executable or by adding:
static {
if (System.getProperty("java.util.logging.manager") == null) {
System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
}
}
at the top of your main class.
Setting this property will replace the default JUL LogManager
implementation with a custom implementation that translates JUL Logger
method calls into Log4j Logger
calls with a minimal overhead.
LogManager
-specific features
The use of a
java.util.logging.Filter
is supported on a
per-Logger
basis.
However, it is recommended to use the standard Filters feature in Log4j instead.
The use of
java.util.logging.Handler
classes is not supported.
Custom handlers should be replaced with the appropriate
Log4j Appender.
Using Log4jBridgeHandler
Are you a Spring Boot user?
Spring Boot will automatically configure |
If setting the java.util.logging.manager
system property is not possible, the JUL-to-Log4j bridge offers an implementation of JUL’s
Handler
abstract class, which redirects all log events to Log4j Core:
org.apache.logging.log4j.jul.Log4jBridgeHandler
.
The |
In order to use Log4jBridgeHandler
you can either:
-
modify the default JUL configuration file
logging.properties
to only contain:# Set Log4jBridgeHandler as only handler for all JUL loggers handlers = org.apache.logging.log4j.jul.Log4jBridgeHandler
See the JRE documentation for details about the format and location of the
logging.properties
file. -
or call the
Log4jBridgeHandler.install()
method in your code.
Usage of Consider setting |
You can tune the behavior of Log4jBridgeHandler
by adding the following properties to the logging.properties
configuration file, which are also available as parameters to the install()
method call:
sysoutDebug
Property name |
|
---|---|
|
N/A |
Type |
|
Default value |
|
If set to true
the bridge will print diagnostic information on the standard output.
appendSuffix
Property name |
|
---|---|
|
|
Type |
|
Default value |
|
Specifies the suffix to append to the name of all JUL loggers, which allows to differentiate JUL log messages from native Log4j API messages.
propagateLevels
Property name |
|
---|---|
|
|
Type |
|
Default value |
|
The additional overhead of Log4jBridgeHandler
can be especially heavy for disabled log statements.
This is why you must ensure that log event filtering of the Log4j implementation and JUL are aligned.
You can do it by either:
-
configuring JUL loggers with the same levels as the Log4j loggers,
-
or setting this property to
true
, which will perform the synchronization automatically.
Common configuration
Independently of the way you install the JUL-to-Log4j bridge, you can finely tune the behavior of the bridge using the following configuration properties. See Configuration properties for more details.
log4j2.julLevelConverter
Env. variable |
|
---|---|
Type |
|
Default value |
|
Fully qualified name of an alternative org.apache.logging.log4j.jul.LevelConverter
implementation.
log4j2.julLoggerAdapter
Env. variable |
|
---|---|
Type |
|
Default value |
|
Fully qualified class name of the org.apache.logging.log4j.jul.AbstractLoggerAdapter
implementation to use.
This property allows users to choose between two implementations of the logging bridge:
org.apache.logging.log4j.jul.CoreLoggerAdapter
-
It allows users to modify the Log4j Core configuration through the JUL
Logger
interface. It requires the usage of the Log4j Core implementation. org.apache.logging.log4j.jul.ApiLoggerAdapter
-
It disables the level mutators in the JUL
Logger
interface.
Since version 2.24.0 the default value changed to |