无法理解为何使用参数化日志记录

时间:2017-09-14 06:50:26

标签: java logging java-8

我正在阅读Java中的参数化日志记录,据说它在执行延迟评估时使用参数化日志记录而不是连接。

所以而不是

logger.debug("My text is" + x);

使用:

logger.debug("My text is {}", x);

如果跟踪级别仅设置为信息日志,为什么连接会在第一个场景中发生?

此外,如果我在日志中有耗时的功能,则说它使用:

logger.debug("My text is {}", () -> compute());

而不是

logger.debug("My text is {}", compute());

在这种情况下,为什么lambda方法被认为是更好的方法。不会像在字符串连接情况下一样被称为懒惰计算吗?

3 个答案:

答案 0 :(得分:9)

在输入logger.debug()之前,必须计算参数。

在第一种情况下,在将生成的String传递给方法(可能不使用它)之前,始终会获得字符串连接。使用参数化版本不会进行连接,x将被传入并可以使用或不使用。

compute()相同的交易。在输入方法之前,非lambda版本将始终执行compute(),因为它需要compute()的结果才能调用该方法。

lambda版本将传递方法(实际上是Supplier,它在请求结果时运行该方法)作为参数而不是方法结果,并且它只会被执行如果需要的话。

答案 1 :(得分:5)

这个想法很简单。通常,应用程序非常频繁地使用logger,但是日志记录本身是耗费资源的操作,至少因为您需要向硬盘驱动器写入内容。看看你的例子:

logger.debug("My text is " + x);

让我们假设在记录器配置中启用了INFO级别。然后代码执行这一行,它需要评估参数以传递debug函数,所以它确实如此。但是在debug内部记录器将检查打开的日志级别,它将是INFO。在这种情况下,不应记录您想要的消息,因此组装参数字符串所需的计算将被视为浪费时间。 要解决此类问题,您可以在调用方法之前检查日志级别是否已转换,如此

if (logger.isDebugEnabled()) {
    logger.debug("My text is " + x)
}

它会更好,因为你只会收集消息,但这里的问题是logger.isDebugEnabled()评估了两次。首先在代码中,然后在logger.debug()内。 这就是参数化日志记录的原因,因为它将这两个问题都抛在了后面。 这同样适用于lambdas建议的耗时操作。希望现在对你有所帮助,有点清楚!

答案 2 :(得分:1)

这与Optional.orElse() vs Optional.orElseGet()几乎完全相同,第二个只在需要时调用。

我假设记录器在内部检查这样的事情:

if(logLevel.isDebug()){

       Value v = supplier.get(); 
       // log v
}

假设你的lambda使用了一些繁重的调用来计算这个值(比如DB call),你肯定不会在需要的时候一直不想要计算