【发布时间】: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].