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

时间:2016-03-10 04:10:12

标签: 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());

那有什么不同呢?

1 个答案:

答案 0 :(得分:4)

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

但是从未创建过整个日志消息。考虑:

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

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

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

使用lambdas,我们有另一种方法可以将呼叫延迟到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());