【问题标题】:Should we use isDebugEnabled() while logging calculated data with Logback?我们应该在使用 Logback 记录计算数据时使用 isDebugEnabled() 吗?
【发布时间】:2020-01-14 16:24:27
【问题描述】:

虽然在一些教程中,例如hereParametrized logging部分)说Logback消息{}参数化帮助我们避免在记录数据中不必要的计算 (如果日志级别不是 DEBUG):

logger.debug("The bonus for employee {} is {}", 
   employee.getName(), employeeService.calculateBonus(employee));

我测试过(在 logback 版本 1.2.3 上),此优化仅适用于参数对象的不必要的 toString() - 就像 log4jworks

Logback documentation 没有涵盖这个细节。

所以,我们必须对所有“昂贵”的日志记录使用 isDebugEnabled(),对吗?

【问题讨论】:

  • 链接的文章在任何地方都没有说“不必要的计算”。 {} 构造有助于防止将值插入日志文本所需的字符串连接。就是这样。
  • @Andreas,你对字符串连接的看法是绝对正确的——但article 说:...This format ensures that the logger will first verify is the log level is enabled, and only afterward will it determine and use the value of the parameters in the log message. -- 确定和使用。如果你说这篇文章,当然是
  • 是的,那篇文章的作者的措辞有点误导。 calculateBonus() 即使不在调试级别记录也会被调用。作为参数传递给debug()方法的只是确定(啊,它是一个数字)和使用 i> 在调试级别记录时(转换为字符串并连接)。

标签: java logging logback


【解决方案1】:

看看例子here

从 2.4 开始,Logger 接口中添加了方法以支持 lambda 表达式。新方法允许客户端代码延迟记录消息,而无需明确检查是否启用了请求的日志级别。例如,以前有人会这样写:

// pre-Java 8 style optimization: explicitly check the log level
// to make sure the expensiveOperation() method is only called if necessary
 if (logger.isTraceEnabled()) {
     logger.trace("Some long-running operation returned {}", expensiveOperation());
 }

在 Java 8 中,使用 lambda 表达式可以达到相同的效果:

// Java-8 style optimization: no need to explicitly check the log level:
// the lambda expression is not evaluated if the TRACE level is not enabled
logger.trace("Some long-running operation returned {}", () -> expensiveOperation());

【讨论】:

  • 感谢您提供优质信息。当我使用 spring-boot (2.2.2)、slf4j-api:2.0.0-alpha1log4j 实现 (slf4j-log4j12:2.0.0-alpha1) 时,这种方法对我有用。
  • 但是当我尝试使用 Logback (logback-classic:1.3.0-alpha5) 时失败:java.lang.ClassNotFoundException: org.slf4j.impl.StaticLoggerBinder 并且仅适用于不支持 Supplier<?> 在日志消息中的旧 logback 版本。可能你在 Spring boot 中使用了更新的 Logback 并解决了这样的问题?
  • 我刚刚发布了来自 log4j 的示例,以强调扩展方法的问题。我不知道 logback api。
【解决方案2】:

当您进行方法调用时,例如employeeService.calculateBonus(employee),您正在调用该方法。就那么简单。因此,每次点击这条线时,您都在计算员工奖金。这里没有惰性求值。

是否使用log.isDebugEnabled()视情况而定。在这种情况下,如果该方法调用代价高昂,则应将其包装在启用调试的检查中。

在 getter 的情况下,这通常不是必需的。因此,例如,我不会将其包装在 isDebugEnabled 支票中:

log.debug("Calculating bonus for employee {} {}", employee.firstName(), employee.lastName());

这些是返回 String 的简单 getter,因此不会进行昂贵的计算。

【讨论】:

    猜你喜欢
    • 2011-03-06
    • 2017-06-13
    • 2014-04-09
    • 2018-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多