Java 日志记录:slf4j over jul 和 log4j2

Java logging: slf4j over jul and log4j2

应用程序无法覆盖 jullog4j2 日志框架,但可以覆盖:log4jjcllog4j

该应用程序使用 slf4j 桥和 logback 作为日志框架。 该应用程序还依赖并调用使用不同日志记录框架的模块:

  1. 七月,
  2. log4j (v1),
  3. jcl 与 log4j
  4. log4j2.

每个模块都有自己的日志记录配置文件,具体取决于日志记录框架。配置文件在每个模块的resorces中定义。

我尝试强制所有模块,不使用他们自己的日志记录框架和配置,而只是slf4j桥接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 以突出显示该组件中使用的日志记录框架:

  <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>

这里是输出,根据选择和配置的日志框架,它只显示每组日志状态符有不同的格式:

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组不同格式的消息。我正在添加多个桥接库:

<!-- 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 更改了它们的日志记录格式,现在按预期使用主应用程序的日志记录格式。

但是 log4j2 和 jul - 仍然使用它们自己的日志记录格式并且不受此设置的影响。

我读过但是JUL to SLF4J Bridge it did not help. Here is the full code of all modules: logging github repo

我想念什么,请你帮忙。

Log4j 2 仍在使用其自己的配置的原因是因为您仅使用 SLF4J 的 log4j-over-slf4j 用于 Log4j 1(尽管没有明确记录).对于 Log4j 2 到 SLF4J,您还必须添加 Log4j 2 to SLF4J Adapter (dependency information)。

对于 jul-to-slf4j,您必须按照 SLF4JBridgeHandler documentation 中描述的步骤进行操作:

  • 在 JRE 的 logging.properties 文件中指定它。尽管如果您无法控制您的应用程序的环境 运行,这可能不是一个选项。
  • 或以编程方式安装它:
    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();
      }
    }
    

此外,您应该为 Logback 配置 LevelChangePropagator。否则,因为 SLF4J class 只是一个处理程序,降低 SLF4J 日志级别(例如用于调试)对 java.util.logging.

没有影响

但是请注意,重定向 java.util.logging 通常很痛苦,尤其是当您的项目有多个入口点时。您将必须在这些入口点中的每一个中执行 SLF4J 桥初始化检查。

附带说明:java.util.logging 到 Log4j 2 桥接器 (Log4j JDK Logging Adapter) 的情况也好不了多少。该库改为实现 LogManager,因此更紧密地集成到 java.util.logging,但缺点是必须使用系统 属性(或 logging.properties 文件)和必须 在加载 java.util.logging.LogManager 之前指定(这可能不受您的控制),之后无法再指定自定义 LogManager 实现。
还有一个名为 Log4jBridgeHandler 的 JUL 处理程序 class,但它仅存在于尚未发布的 3.0.0 分支中并且尚未向后移植,请参阅 backport pull request