Java日志记录:通过jul和log4j2的slf4j [英] Java logging: slf4j over jul and log4j2
问题描述
应用程序无法覆盖 jul
和 log4j2
日志记录框架,但是可以使用覆盖:
log4j
, jcl
> log4j
Application cannot overwrite jul
and log4j2
logging frameworks, but can ovewrite: log4j
, jcl
with log4j
应用程序使用 slf4j
网桥和 logback
作为日志框架.该应用程序还依赖并调用使用不同日志记录框架的模块:
The application uses slf4j
bridge with logback
as a logging framework.
The application also depends and invokes modules which use different logging frameworks:
- 七月,
- log4j(v1),
- 带有log4j的jcl
- log4j2.
每个模块都有自己的日志记录配置文件,具体取决于日志记录框架.该配置文件在每个模块的 resorces
中定义.
Each module has its own logging configuration file, depending on the logging framework. The config file is defined in the resorces
of each module.
我尝试强制所有模块,不使用它们自己的日志记录框架和配置,而仅使用 slf4j
与 logback
桥接.
I try to force all the modules, do not use their own logging frameworks and configuration, but only slf4j
bridge with logback
.
这是Java代码:
new Slf4jLoggingExample().doLog();
new JulLoggingExample().doLog();
new Log4jLoggingExample().doLog();
new Log4jV2LoggingExample().doLog();
new JclLog4jLoggingExample().doLog();
这是Maven配置没有的多个桥接库,例如log4j-over-slf4j,jul-to-slf4j,jcl-over-slf4j.请注意,工件ID只是自定义组件:在该组件中使用的jul,log4j,log4j-v2,jcl-log4j突出显示了日志记录框架:
Here is the maven configuration WITHOUT multiple bridging libraries, like log4j-over-slf4j, jul-to-slf4j, jcl-over-slf4j. Note, artifact ids are just custom components: jul, log4j,log4j-v2, jcl-log4j to highlight a logging framework, used in that component:
<dependencies>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>com.savdev.example.logging</groupId>
<artifactId>jul</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.savdev.example.logging</groupId>
<artifactId>log4j</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.savdev.example.logging</groupId>
<artifactId>log4j-v2</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.savdev.example.logging</groupId>
<artifactId>jcl-log4j</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
这里是输出,根据选择和配置的日志记录框架,它仅显示每组日志状态菜单具有不同的格式:
Here is the output, which just shows that each set of log statemens have different format, according to the chosen and configured logging framework:
12:18:08.316 [main] INFO c.s.e.logging.Slf4jLoggingExample - This is an info message, (originally, slf4j with logback)
12:18:08.318 [main] ERROR c.s.e.logging.Slf4jLoggingExample - This is an error message, (originally, slf4j with logback)
12:18:08.318 [main] WARN c.s.e.logging.Slf4jLoggingExample - This is a warning message, (originally, slf4j with logback)
12:18:08.318 [main] DEBUG c.s.e.logging.Slf4jLoggingExample - Here is a debug message, (originally, slf4j with logback)
Feb 24, 2021 12:18:08 PM com.savdev.example.logging.jul.JulLoggingExample doLog
INFO: This is an info message (originally, JUL)
Feb 24, 2021 12:18:08 PM com.savdev.example.logging.jul.JulLoggingExample doLog
SEVERE: This is an error message (originally, JUL)
Feb 24, 2021 12:18:08 PM com.savdev.example.logging.jul.JulLoggingExample doLog
WARNING: This is a warning message (originally, JUL)
Feb 24, 2021 12:18:08 PM com.savdev.example.logging.jul.JulLoggingExample doLog
FINE: Here is a debug message (originally, JUL)
[main] INFO com.savdev.example.logging.log4j.Log4jLoggingExample - This is an info message, (originally, log4j)
[main] ERROR com.savdev.example.logging.log4j.Log4jLoggingExample - This is an error message, (originally, log4j)
[main] WARN com.savdev.example.logging.log4j.Log4jLoggingExample - This is a warning message, (originally, log4j)
[main] DEBUG com.savdev.example.logging.log4j.Log4jLoggingExample - Here is a debug message, (originally, log4j)
[INFO ] 2021-02-24 12:18:08.722 [main] Log4jV2LoggingExample - This is an info message, (originally, log4j2)
[ERROR] 2021-02-24 12:18:08.724 [main] Log4jV2LoggingExample - This is an error message, (originally, log4j2)
[WARN ] 2021-02-24 12:18:08.724 [main] Log4jV2LoggingExample - This is a warning message, (originally, log4j2)
[DEBUG] 2021-02-24 12:18:08.724 [main] Log4jV2LoggingExample - Here is a debug message, (originally, log4j2)
[main] INFO com.savdev.example.logging.jcl.logback.JclLog4jLoggingExample - This is an info message (originally, jcl with log4j)
[main] ERROR com.savdev.example.logging.jcl.logback.JclLog4jLoggingExample - This is an error message (originally, jcl with log4j)
[main] WARN com.savdev.example.logging.jcl.logback.JclLog4jLoggingExample - This is a warning message (originally, jcl with log4j)
[main] DEBUG com.savdev.example.logging.jcl.logback.JclLog4jLoggingExample - Here is a debug message (originally, jcl with log4j)
5组不同格式的消息.我要添加多个桥接库:
5 groups of messages with different format. I am adding multiple bridging libraries:
<!-- https://mvnrepository.com/artifact/org.slf4j/jul-to-slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.30</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/log4j-over-slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.30</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/jcl-over-slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.30</version>
</dependency>
这是新的输出:
12:44:40.385 [main] INFO c.s.e.logging.Slf4jLoggingExample - This is an info message, (originally, slf4j with logback)
12:44:40.387 [main] ERROR c.s.e.logging.Slf4jLoggingExample - This is an error message, (originally, slf4j with logback)
12:44:40.387 [main] WARN c.s.e.logging.Slf4jLoggingExample - This is a warning message, (originally, slf4j with logback)
12:44:40.387 [main] DEBUG c.s.e.logging.Slf4jLoggingExample - Here is a debug message, (originally, slf4j with logback)
12:44:40.399 [main] INFO c.s.e.l.log4j.Log4jLoggingExample - This is an info message, (originally, log4j)
12:44:40.400 [main] ERROR c.s.e.l.log4j.Log4jLoggingExample - This is an error message, (originally, log4j)
12:44:40.400 [main] WARN c.s.e.l.log4j.Log4jLoggingExample - This is a warning message, (originally, log4j)
12:44:40.400 [main] DEBUG c.s.e.l.log4j.Log4jLoggingExample - Here is a debug message, (originally, log4j)
Feb 24, 2021 12:44:40 PM com.savdev.example.logging.jul.JulLoggingExample doLog
INFO: This is an info message (originally, JUL)
Feb 24, 2021 12:44:40 PM com.savdev.example.logging.jul.JulLoggingExample doLog
SEVERE: This is an error message (originally, JUL)
Feb 24, 2021 12:44:40 PM com.savdev.example.logging.jul.JulLoggingExample doLog
WARNING: This is a warning message (originally, JUL)
Feb 24, 2021 12:44:40 PM com.savdev.example.logging.jul.JulLoggingExample doLog
FINE: Here is a debug message (originally, JUL)
[INFO ] 2021-02-24 12:44:40.793 [main] Log4jV2LoggingExample - This is an info message, (originally, log4j2)
[ERROR] 2021-02-24 12:44:40.795 [main] Log4jV2LoggingExample - This is an error message, (originally, log4j2)
[WARN ] 2021-02-24 12:44:40.795 [main] Log4jV2LoggingExample - This is a warning message, (originally, log4j2)
[DEBUG] 2021-02-24 12:44:40.796 [main] Log4jV2LoggingExample - Here is a debug message, (originally, log4j2)
12:44:40.798 [main] INFO c.s.e.l.j.l.JclLog4jLoggingExample - This is an info message (originally, jcl with log4j)
12:44:40.798 [main] ERROR c.s.e.l.j.l.JclLog4jLoggingExample - This is an error message (originally, jcl with log4j)
12:44:40.798 [main] WARN c.s.e.l.j.l.JclLog4jLoggingExample - This is a warning message (originally, jcl with log4j)
12:44:40.798 [main] DEBUG c.s.e.l.j.l.JclLog4jLoggingExample - Here is a debug message (originally, jcl with log4j)
我看到的是,只有具有log4j的组件和具有log4j的jcl组件更改了日志记录格式,并且现在按预期使用了主应用程序的日志记录格式.
What I can see, only the components with log4j and jcl with log4j changed their logging format and now use as expected the logging format of the main application.
但是log4j2和jul-仍使用其自己的日志记录格式,不受此设置的影响.
But log4j2 and jul - still use their own logging format and are not affected by this setup.
我已阅读但从JUL到SLF4J Bridge 并没有帮助.这是所有模块的完整代码:记录github存储库
I have read but JUL to SLF4J Bridge it did not help. Here is the full code of all modules: logging github repo
我想念什么,请您帮忙.
What do I miss, can you please help.
推荐答案
Log4j 2仍使用其自身配置的原因是因为您仅使用SLF4J的 log4j-over-slf4j
Log4j 1 (尽管没有明确记录).对于Log4j 2到SLF4J,您必须添加 Log4j2到SLF4J适配器(依赖性信息).
The reason why Log4j 2 is still using its own configuration is because you are only using SLF4J's log4j-over-slf4j
which is for Log4j 1 (despite not being that clearly documented). For Log4j 2 to SLF4J, you will have to add Log4j 2 to SLF4J Adapter (dependency information) as well.
For jul-to-slf4j
you have to follow the steps described in the SLF4JBridgeHandler
documentation:
- 在您的JRE的
logging.properties
文件中进行指定.尽管如果您无法控制应用程序正在运行的环境,那么这可能不是一个选择. - 或以编程方式安装它:
- Either specify it in the
logging.properties
file of your JRE. Though if you have no control over the environment your application is running, this is likely not an option. - Or programmatically install it:
static {
// Verify that it is not installed yet; other dependency might have already
// installed it which would cause duplicate handler
// Unfortunately SLF4J provides no built-in method for this procedure, so
// race condition between different classes could happen
if (!SLF4JBridgeHandler.isInstalled()) {
// Remove default handler logging to System.err
SLF4JBridgeHandler.removeHandlersForRootLogger();
// Install the SLF4J handler
SLF4JBridgeHandler.install();
}
}
此外,您还应该配置 LevelChangePropagator
用于Logback.否则,由于SLF4J类只是一个处理程序,因此降低SLF4J日志级别(例如,用于调试)将不会影响 java.util.logging
.
Additionally you should configure the LevelChangePropagator
for Logback. Otherwise, because the SLF4J class is only a handler, lowering the SLF4J log level (e.g. for debugging) would have no effect on java.util.logging
.
但是请注意,通常重定向 java.util.logging
会很麻烦,尤其是在您的项目有多个入口点的情况下.您将必须在每个这些入口点中执行SLF4J桥初始化检查.
Note however, that redirecting java.util.logging
in general is a pain, especially if your project has multiple entry points. You will have to perform the SLF4J bridge initialization check in every one of these entry points.
作为旁注: java.util.logging
到Log4j 2桥的情况(反向请求请求.
As a side note: The situation for the java.util.logging
to Log4j 2 bridge (Log4j JDK Logging Adapter) it is not much better. That library instead implements LogManager
which therefore integrates more tightly into java.util.logging
, but has the disadvantage that it has to be specified using a System property (or the logging.properties
file) and must be specified before java.util.logging.LogManager
is loaded (which might not be in your control), afterwards a custom LogManager
implementation cannot be specified anymore.
There is also a JUL Handler class called Log4jBridgeHandler
, but that only exists on the not yet released 3.0.0 branch and has not been backported yet, see backport pull request.
这篇关于Java日志记录:通过jul和log4j2的slf4j的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!