我在我的应用程序中使用Log4J进行日志记录。之前我使用的调试调用如下:

选项1:

logger.debug("some debug text");

但是一些链接建议最好先检查isDebugEnabled(),比如:

选项2:

boolean debugEnabled = logger.isDebugEnabled();
if (debugEnabled) {
    logger.debug("some debug text");
}

所以我的问题是“选项2是否能提高性能?”

因为在任何情况下Log4J框架对debugEnabled都有相同的检查。对于选项2,如果我们在一个方法或类中使用多个调试语句可能是有益的,这样框架就不需要多次调用isDebugEnabled()方法(每次调用);在这种情况下,它只调用isDebugEnabled()方法一次,如果Log4J被配置为调试级别,那么实际上它会调用isDebugEnabled()方法两次:

如果将值分配给debugEnabled变量,和 实际上由logger.debug()方法调用。

我不认为如果我们在方法或类中编写多个logger.debug()语句并根据选项1调用debug()方法,那么与选项2相比,Log4J框架的开销是很大的。由于isDebugEnabled()是一个非常小的方法(就代码而言),因此它可能是内联的良好候选方法。


当前回答

我建议大多数人使用选项2,因为它不是特别贵。

案例1: log.debug(一个字符串)

例2: Log.debug(“一个字符串”+“两个字符串”+对象。toString + object2.toString)

在调用这两个函数时,必须计算log.debug中的参数字符串(无论是CASE 1还是Case2)。这就是人们所说的“昂贵”。如果你在它之前有一个条件,'isDebugEnabled()',这些不需要计算,这是性能保存的地方。

其他回答

Log4j2允许您将参数格式化为消息模板,类似于String.format(),因此不需要执行isDebugEnabled()。

Logger log = LogManager.getFormatterLogger(getClass());
log.debug("Some message [myField=%s]", myField);

简单的log4j2.properties示例:

filter.threshold.type = ThresholdFilter
filter.threshold.level = debug
appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %d %-5p: %c - %m%n
appender.console.filter.threshold.type = ThresholdFilter
appender.console.filter.threshold.level = debug
rootLogger.level = info
rootLogger.appenderRef.stdout.ref = STDOUT

在这种特殊情况下,选择1更好。

当涉及调用各种对象的toString()方法并连接结果时,保护语句(检查isDebugEnabled())是为了防止日志消息潜在的昂贵计算。

在给定的示例中,日志消息是一个常量字符串,因此让记录器丢弃它与检查记录器是否启用一样有效,并且由于分支较少,因此降低了代码的复杂性。

更好的方法是使用最新的日志记录框架,其中日志语句接受一个格式规范和一个参数列表,由日志记录器代替——但是“惰性地”,只有在启用了日志记录器的情况下。这是slf4j采用的方法。

有关更多信息,请参阅我对相关问题的回答,以及使用log4j执行类似操作的示例。

在Java 8中,您不必使用isDebugEnabled()来提高性能。

https://logging.apache.org/log4j/2.0/manual/api.html#Java_8_lambda_support_for_lazy_logging

import java.util.logging.Logger;
...
Logger.getLogger("hello").info(() -> "Hello " + name);

简短版本:你也可以做布尔isDebugEnabled()检查。

原因: 1-如果复杂的逻辑/字符串连接。添加到调试语句时,则检查已经就位。 2-你不必有选择地在“复杂”调试语句中包含语句。所有语句都是这样包含的。 3-在记录日志之前,调用log.debug执行以下命令:

如果(repository.isDisabled (Level.DEBUG_INT)) 返回;

这基本上与调用log相同。或猫。isDebugEnabled()。

然而!这是log4j开发人员的想法(因为它在他们的javadoc中,您可能应该遵循它)。

这就是方法

public
  boolean isDebugEnabled() {
     if(repository.isDisabled( Level.DEBUG_INT))
      return false;
    return Level.DEBUG.isGreaterOrEqual(this.getEffectiveLevel());
  }

这是它的javadoc

/**
*  Check whether this category is enabled for the <code>DEBUG</code>
*  Level.
*
*  <p> This function is intended to lessen the computational cost of
*  disabled log debug statements.
*
*  <p> For some <code>cat</code> Category object, when you write,
*  <pre>
*      cat.debug("This is entry number: " + i );
*  </pre>
*
*  <p>You incur the cost constructing the message, concatenatiion in
*  this case, regardless of whether the message is logged or not.
*
*  <p>If you are worried about speed, then you should write
*  <pre>
*    if(cat.isDebugEnabled()) {
*      cat.debug("This is entry number: " + i );
*    }
*  </pre>
*
*  <p>This way you will not incur the cost of parameter
*  construction if debugging is disabled for <code>cat</code>. On
*  the other hand, if the <code>cat</code> is debug enabled, you
*  will incur the cost of evaluating whether the category is debug
*  enabled twice. Once in <code>isDebugEnabled</code> and once in
*  the <code>debug</code>.  This is an insignificant overhead
*  since evaluating a category takes about 1%% of the time it
*  takes to actually log.
*
*  @return boolean - <code>true</code> if this category is debug
*  enabled, <code>false</code> otherwise.
*   */

Since in option 1 the message string is a constant, there is absolutely no gain in wrapping the logging statement with a condition, on the contrary, if the log statement is debug enabled, you will be evaluating twice, once in the isDebugEnabled() method and once in debug() method. The cost of invoking isDebugEnabled() is in the order of 5 to 30 nanoseconds which should be negligible for most practical purposes. Thus, option 2 is not desirable because it pollutes your code and provides no other gain.