【问题标题】:Why (in some cases) does logback invoke toString() even though logging level is disabled?为什么(在某些情况下)即使日志级别被禁用,logback 也会调用 toString()?
【发布时间】:2014-06-04 15:43:13
【问题描述】:

我们最近在我们的系统中遇到了性能问题,Logback 调用了 toString(),即使没有为该特定记录器启用指定的日志记录级别 (DEBUG)。当然,另一个问题是我们的 toString() 方法非常占用 CPU,但这是 logback 非常意外的行为。鉴于以下简单的测试用例,未指定 mypkg.LogTest2 的日志级别(默认),我看到 toString() 调用了两次,但没有打印日志消息(注意:链接到 logback-classic-0.9.29 和 logback-core- 0.9.29)。

package mypkg;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LogTest2 {
   private static Logger ROOT_LOGGER = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
   private static Logger CLASS_LOGGER = LoggerFactory.getLogger(LogTest2.class);

   public static void main(String[] args){
      LogTest2 obj = new LogTest2();
   }
   public LogTest2() {
      if (CLASS_LOGGER.isDebugEnabled()) {
         ROOT_LOGGER.info("A CLASS_LOGGER debug guarded ROOT_LOGGER info message: {}", this);
         CLASS_LOGGER.debug("A class logger debug message: {}", this);
      }
   }
   public String toString() {
      System.out.println("================= LogTest2 toString invoked.");
      return "{LogTest2}";
   }
}

上述程序的输出:

================= LogTest2 toString invoked.
================= LogTest2 toString invoked.

为了完整起见,这里是我正在使用的 logback.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<configuration  scan="true" debug="true">
  <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
    <encoder><pattern>%c -> %msg%n</pattern></encoder>
  </appender>

  <!--  
  <logger name="mypkg" level="debug">  <appender-ref ref="stdout" />  </logger>
  -->
</configuration>

如果我更新上述 logback.xml 文件以取消注释“mypkg”记录器,输出会更改,但仍会额外调用一次 toString():

================= LogTest2 toString invoked.
================= LogTest2 toString invoked.
mypkg.LogTest2 -> A class logger debug message: {LogTest2}

这违背了我对 slf4j 和 logback 日志应该如何工作的所有理解。谁能帮我理解这一点?这是错误还是预期行为(以及为什么)?

【问题讨论】:

  • 我可以确认在较新版本的 Logback 中不会发生这种情况,尤其是 1.1.2。
  • 我刚刚在 logback 1.0.3(我们在项目中安装的当前最新版本)尝试了这个,虽然它仍然具有相同的行为,但我从 logback 中收到了一条新的有用的警告消息:WARN in Logger[ROOT] - No appenders present in context [default] for logger [ROOT].

标签: java logging logback


【解决方案1】:

ROOT 记录器是使用 DEBUG 级别创建的。创建子记录器时,其有效日志记录级别设置为其父记录器的记录级别。此外,isDebugEnabled() 检查Loggerint 值)的有效日志记录级别是否为&gt;=DEBUG 的值。在这种情况下,它是相等的,因为它是从 ROOT 继承的。

在您没有声明记录器的示例中,它也没有任何附加程序。消息被构建,但没有地方可以记录它。因此,虽然调试级别确实得到满足,但它不会在任何地方记录。

在较新版本的 logback 中,似乎在检查 appender 后日志消息构建完成。

【讨论】:

  • 真正让我震惊的是ROOT_LOGGER.info(....) 语句被执行,但没有被记录。我猜这是因为它没有附加程序(显然根记录器没有默认附加程序)。
  • @OgrePsalm33 对。声明Appender 不会向任何Logger、root 或其他方式注册它。
猜你喜欢
  • 1970-01-01
  • 2017-08-19
  • 2015-11-25
  • 1970-01-01
  • 1970-01-01
  • 2011-07-27
  • 2021-04-02
  • 1970-01-01
  • 2019-12-18
相关资源
最近更新 更多