为什么(在某些情况下)即使禁用了日志记录级别,logback也会调用toString()?

时间:2014-06-04 15:43:14

标签: java logging logback

我们最近在我们的系统中遇到了性能问题,即使没有为该特定记录器启用指定的日志记录级别(DEBUG),Logback也会调用toString()。当然,另外一个问题是我们的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文件以取消注释&#34; mypkg&#34;记录器,输出发生了变化,但仍然会调用toString()一个额外的时间:

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

这违背了我对slf4j和logback日志记录假设如何工作的理解。任何人都可以帮我理解这个吗?这是一个错误或预期的行为(以及为什么)?

1 个答案:

答案 0 :(得分:1)

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

在您没有声明记录器的示例中,它也没有任何appender。邮件已构建,但无法将其记录到何处。因此,虽然调试级别确实得到满足,但它并没有记录到任何地方。

在较新版本的logback中,看来日志消息构造是在检查了appender之后完成的。