java - 在有效日志级别检查的上下文中,Log4j2 中的替换参数和 Java lambda 表达式有什么区别?

标签 java logging lambda log4j log4j2

我试图了解 Log4j 2.x 的好处,但 documentation让我感到困惑。 分为两部分:替换参数和 Java 8 lambda 对惰性日志记录的支持。

在第一个中说使用:

logger.debug("Logging in user {} with birthday {}", user.getName(), user.getBirthdayCalendar());

足以不检查日志记录级别两次。

另一方面,在第二部分中他们说我应该使用 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 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());

那有什么区别呢?

最佳答案

在第一部分中,调用了user.getName(),并将值传递给了logger.debug()函数。如果禁用调试日志记录,则丢弃该值。获取用户名可能是“昂贵的”;它可以存储为名字、姓氏、前缀和后缀,并构建成更大的字符串。如果不使用该值,那就是浪费精力。

但从未创建完整的日志消息。考虑:

logger.debug("Logging in user " + user.getName() + " with birthday " + user.getBirthdayCalendar());

在这里,我们不仅调用了 getName()getBirthdayCalender(),而且还进行了字符串连接以构建整个日志消息!至少在使用 {} 替换代码时,记录器可以意识到,如果它不记录调试消息,则不必进行字符串替换。程序员需要为该优化添加 if (isDebugEnabled() 语句。

在第二个示例中,isTraceEnabled() 验证在调用尝试在跟踪级别记录某些内容的语句之前,该值实际上将由记录器记录。 expensiveOperation() 仅在启用“跟踪”日志记录时执行。

使用 lambda,我们有另一种方法来延迟对 expensiveOperation() 的调用:

logger.trace("Some long-running operation returned {}", () -> expensiveOperation());

不是计算 expensiveOperation(),我们只是传递一个函数,可以调用它来执行昂贵的操作。如果启用跟踪级别日志记录,记录器将自己调用 lambda 函数,调用昂贵的操作函数。如果未启用跟踪日志记录,则不会调用 lambda 函数,因此永远不会执行昂贵的操作。


总而言之,如果禁用跟踪级日志记录:

// Calls expensiveOperation & builds log string:
logger.trace("Some long running operation returned "+expensiveOperation())

// Calls expensiveOperation, but does not build log string:
logger.trace("Some long-running operation returned {}", expensiveOperation());

// Does not call expensiveOperation, nor builds log string:
logger.trace("Some long-running operation returned {}", () -> expensiveOperation());

关于java - 在有效日志级别检查的上下文中,Log4j2 中的替换参数和 Java lambda 表达式有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35907427/

相关文章:

java - 如何只使用对象的几个字段进行 REST 服务

java - 将表名作为准备语句的参数传递

java - 如何在 Android 中创建锁 (concurrent.locks.Lock)?

android - 隐藏 Ormlite 的调试日志

android - 如何在 Android 上配置 java.util.logging?

c++ - C++11 lambda 表达式背后的动机是什么?

lambda - 在函数调用中作为参数传递时,粗箭头语法的含义是什么?

Java Netty 3.3.1.Final,DynamicChannelBuffer.java :75, 无限循环,一个错误?

logging - 如何抑制继承的项目 logback.xml 文件(单个项目中有 2 个 logback.xml)?

python - 这个命令到底是做什么的?