我们最近在我们的系统中遇到了性能问题,即使没有为该特定记录器启用指定的日志记录级别(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日志记录假设如何工作的理解。任何人都可以帮我理解这个吗?这是一个错误或预期的行为(以及为什么)?
答案 0 :(得分:1)
ROOT记录器的创建级别为DEBUG。创建子记录器时,其有效日志记录级别设置为其父级记录级别。此外,isDebugEnabled()
会检查Logger
(int
值)的有效日志记录级别>=
是否为DEBUG
。在这种情况下,它是相同的,因为它是从ROOT继承的。
在您没有声明记录器的示例中,它也没有任何appender。邮件已构建,但无法将其记录到何处。因此,虽然调试级别确实得到满足,但它并没有记录到任何地方。
在较新版本的logback中,看来日志消息构造是在检查了appender之后完成的。