将对 debug() 的调用包含在 if isDebugEnabled() 中):一个好的策略?

2022-09-01 15:16:43

我们的团队有做日志记录的政策,比如

if (LOGGER.isDebugEnabled()) {  
  LOGGER.debug("model[" + model + "]");
}

而不是简单地调用日志记录方法,如下所示:

LOGGER.debug("model[" + model + "]");

这种做法能够带来一些性能改进,但另一方面,它使代码库更加复杂。我们的应用程序没有性能问题,可能永远不会,引入策略的论点只是这是一个很好的做法,所以每次我们进行日志记录时都会使用它。

你认为这是一个好政策吗?


答案 1

您应该使用 SLF4J 并使 log4j 成为您的实现。使用 SLF4J,您可以通过使用参数化消息完全消除。isDebugEnabled()

请参阅 slf4j 常见问题解答中有关日志记录性能的部分

以下两行将产生完全相同的输出。但是,在禁用日志记录语句的情况下,第二种形式的性能将比第一种形式的性能至少高出 30 倍。

logger.debug("The new entry is " + entry + ".");

logger.debug("The new entry is {}.", entry);


答案 2

对于那些正在构建的日志字符串实际上会显著影响性能的情况,这是一个很好的策略。这可能有两个原因:

  • 构建字符串需要做很多工作(例如,它必须进行查找,或者从许多非常小的部分构建一个非常大的字符串)
  • 它位于一个循环中,该循环不做太多其他工作(但经常被调用),因此即使构建简单的日志字符串所花费的时间比例也更高

这不应该是一个一揽子规则,我预计这两种情况都相对罕见。

当然,我们真正想要的是能够说,“调用调试方法,传入一个不是调试字符串本身的参数,而是知道如何构建调试字符串的东西,当且仅当它是必需的。这在Java中如果没有简洁的闭包,这将是丑陋的。(即使在以 lambda 表达式形式进行闭包的语言中,在某些情况下捕获相关变量也可能很重要,具体取决于语言如何处理捕获。


推荐