我们知道我们可以通过其属性/配置文件来配置log4j来关闭特定位置(Java中的类或包)的日志。我的问题是:
感谢,
答案 0 :(得分:16)
是的,日志语句仍将执行。这就是为什么首先检查日志级别是一个很好的模式:类似
if (log.isInfoEnabled()) {
log.info("My big long info string: " + someMessage);
}
这是为了防止在日志级别不支持String
语句时为信息INFO
重新分配空间。
它不是#ifdef
- #ifdef
是编译器指令,而Log4J配置是在运行时处理的。
编辑:我讨厌由于无知导致失败,所以这里有一篇文章支持我的回答。
来自http://surguy.net/articles/removing-log-messages.xml:
在Log4J中,如果您在其中记录消息 DEBUG级别和当前的Appender 设置为仅记录INFO的消息 级别及以上,然后消息将 不显示。表现 调用日志方法的惩罚 本身很小 - 几纳秒。 但是,可能需要更长时间 评估日志的参数 方法。例如:
logger.debug(“大对象是 “+ largeObject.toString());
评估largeObject.toString()可能 要慢,然后进行评估 调用记录器,所以记录器 不能阻止它被评估, 即使它不会被使用。
编辑2 :来自log4j手册本身(http://logging.apache.org/log4j/1.2/manual.html):
用户应了解以下性能问题。
关闭日志记录时的记录性能。 当完全关闭日志记录或仅针对一组级别关闭日志记录时,日志请求的开销包括方法调用和整数比较。在233 MHz Pentium II机器上,此成本通常在5到50纳秒范围内。
但是,方法调用涉及参数构造的“隐藏”成本。
例如,对于某些记录器猫,写作,
logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
会产生构造消息参数的成本,即将integer i和entry [i]都转换为String,并连接中间字符串,无论是否记录消息。参数构造的成本可能非常高,并且取决于所涉及参数的大小。
为避免参数构造成本写:
if(logger.isDebugEnabled() {
logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
}
如果禁用调试,这不会产生参数构造的成本。另一方面,如果记录器是启用调试的,则会产生两倍于评估记录器是否启用的成本:一次在debugEnabled中,一次在调试中。这是一个微不足道的开销,因为评估记录器需要大约1%的时间来实际记录。
答案 1 :(得分:5)
我运行了一个简单的基准测试。
for (int j = 0; j < 5; j++) {
long t1 = System.nanoTime() / 1000000;
int iterations = 1000000;
for (int i = 0; i < iterations; i++) {
int test = i % 10;
log.debug("Test " + i + " has value " + test);
}
long t2 = System.nanoTime() / 1000000;
log.info("elapsed time: " + (t2 - t1));
long t3 = System.nanoTime() / 1000000;
for (int i = 0; i < iterations; i++) {
int test = i % 10;
if (log.isDebugEnabled()) {
log.debug("Test " + i + " has value " + test);
}
}
long t4 = System.nanoTime() / 1000000;
log.info("elapsed time 2: " + (t4 - t3));
}
elapsed time: 539
elapsed time 2: 17
elapsed time: 450
elapsed time 2: 18
elapsed time: 454
elapsed time 2: 19
elapsed time: 454
elapsed time 2: 17
elapsed time: 450
elapsed time 2: 19
1.6.0_18,让我感到惊讶,因为我认为内联会阻止这一点。也许带有转义分析的Java 7会。
但是我仍然不会在if子句中包装调试语句,除非半微秒的时间改进变得很重要!
答案 2 :(得分:1)
log4j将处理日志语句,并检查特定日志记录器是否在特定日志记录级别启用。如果不是,则不会记录该语句。
这些检查比实际写入磁盘(或控制台)要便宜得多,但它们仍有影响。
不,java没有像#ifdef这样的概念(无论如何都有开箱即用的java预编译器)