关于golang:Java日志框架中需要判断logisDebugEnabled吗

42次阅读

共计 2825 个字符,预计需要花费 8 分钟才能阅读完成。

Java 日志框架中须要判断 log.isDebugEnabled()吗?

背景

在日常开发中,我的项目会应用形象日志接口 slf4j 来打印日志。如下是一段典型的打印日志代码:

logger.debug("hello, world");

然而在一些我的项目或第三方开源框架中,也会发现有些代码在输入日志时,在后面增加 if 判断,代码如下:

if(logger.isDebugEnabled()){logger.debug("hello, world");
}

简略来说,先应用 isDebufEnabled 来判断日志级别。这么写的目标是什么呢?而且网上有些文档指出这种判断其实是不须要的。那理论开发中,咱们到底要不要判断 isDebugEnabled 呢?心愿通过这篇文章来分享一些我对日志打印的思考。

简略的源码分析

有些人不明确为什么要增加 if 判断,会认为这样是为了管制日志的输入。其实这是不对的。对于上面的两段代码:

logger.debug("hello, world")
if(logger.isDebugEnabled()){logger.debug("hello, world");
}

如果利用的日志级别大于 debug,比方为info。那么这两段代码,最终都不会输入日志。在debug 办法外部,会判断日志级别,如果利用级别大于日志级别,就不会输入日志。以下是 isDebugEnableddebug的外围代码(我删除了一些无关代码):

isDebugEnabled办法:

public boolean isDebugEnabled(Marker marker) {final FilterReply decision = callTurboFilters(marker, Level.DEBUG);
        if (decision == FilterReply.NEUTRAL) {return effectiveLevelInt <= Level.DEBUG_INT;} else {throw new IllegalStateException("Unknown FilterReply value:" + decision);
        }
    }

debug办法:

private void filterAndLog_0_Or3Plus(final String localFQCN, final Marker marker, final Level level, final String msg, final Object[] params,
                    final Throwable t) {final FilterReply decision = loggerContext.getTurboFilterChainDecision_0_3OrMore(marker, this, level, msg, params, t);

        if (decision == FilterReply.NEUTRAL) {if (effectiveLevelInt > level.levelInt) {return;}
        } else if (decision == FilterReply.DENY) {return;}

        buildLoggingEventAndAppend(localFQCN, marker, level, msg, params, t);
    }

那么问题来了,既然 isDebugEnabled 不会影响日志是否输入,那为什么要增加这个判断呢?

为什么要增加 if 判断

咱们思考上面几段代码:

代码清单一:

logger.debug("hello, world")

代码清单二:

if(logger.isDebugEnabled()){logger.debug("hello, world")
}

代码清单三:

logger.debug("hello" + "world");

代码清单四:

logger.debug(String.format("hello, %s", "world"))

代码清单五:

logger.debug("hello {}", "world");

以上 5 段代码,如果利用日志级别为 info,那么这 5 段代码都不会输入日志。它们的差别其实是 性能不同。上面咱们来一一剖析。

  • 代码清单一:执行 debug 办法。debug办法外部判断日志级别,而后退出。
  • 代码清单二:isDebugEnabled判断日志级别,而后退出。
  • 代码清单三:先拼接字符串“hello”和“world”。而后执行 debug 办法。
  • 代码清单四:先执行 String.format 办法,而后执行 debug 办法。
  • 代码清单五:执行 debug 办法。

大家发现了吗?尽管最终都不会输入日志,但这 5 段代码还是有差别的。代码清单三和代码清单四别离执行了 ”+” 字符串拼接和 String.format 办法,但最终却没用到。也就是说,这两段代码执行了一些无用操作,造成了额定的性能损耗。

所以,代码清单二中增加 isDebugEnabled 能够防止无用的字符串操作,进步性能。

isDebugEnabled是必须的吗?

上一节中,我提到应用 isDebugEnabled 能够晋升性能,那是不是在所有中央都须要增加 isDebugEnabled 判断呢?

先说论断,不是的。应该依据具体场景来判断是否增加isDebugEnabled

比方上面的代码:

logger.debug("hello, world");

打印一条日志“hello,world”。那么这时候就不必增加 isDebugEnabled 判断了。对于 isDebugEnabled 的应用场景,总结了如下的最佳实际:

isDebugEnabled最佳实际

准则一:如果打印字符串常量,不须要isDebugEnabled

比拟上面两段代码:

logger.debug("hello, world");
if(logger.isDebugEnabled()){logger.debug("hello, world");
}

因为打印的日志是字面常量,没有计算逻辑。两段代码的性能是简直一样的。增加 isDebugEnabled 反而会导致额定的代码。

准则二:如果有参数,且参数只是字符串常量或计算简略,应用占位符

思考如下代码,debug办法蕴含了参数 user.getName()。尽管执行debug 办法时,会计算 user.getName(),但只是一个简略的get 办法,没有简单计算,这时候,也能够不增加isDebugEnabled

logger.debug("hello, {}", user.getName());

准则三:如果有参数,且参数计算简单,增加isDebugEnabled

logger.debug("order price: {}", calculatePrice());

假如 calculatePrice 办法须要通过简单计算。那么就应该增加 isDebugEnabled 判断,应用如下的代码:

if(logger.isDebugEnabled()){logger.debug("order price: {}", calculatePrice());
}

正文完
 0