Java 日志记录:slf4j over jul 和 log4j2

时间:2021-02-24 11:51:58

标签: java logging log4j2 slf4j

应用程序不能覆盖 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 配置 WITHOUT 多个桥接库,如 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 没有帮助。以下是所有模块的完整代码:logging github repo

我有什么想念的,你能帮忙吗。

1 个答案:

答案 0 :(得分:1)

Log4j 2 仍然使用自己的配置的原因是因为您只使用 SLF4J 的 required: true,它用于 Log4j 1(尽管没有明确记录)。对于 Log4j 2 到 SLF4J,您还必须添加 Log4j 2 to SLF4J Adapter (dependency information)。

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

  • 在 JRE 的 jul-to-slf4j 文件中指定它。但是,如果您无法控制应用程序运行的环境,这可能不是一种选择。
  • 或者以编程方式安装它:
    logging.properties

此外,您应该为 Logback 配置 LevelChangePropagator。否则,因为 SLF4J 类只是一个处理程序,降低 SLF4J 日志级别(例如用于调试)不会对 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(); } } 产生影响。

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

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