即使使用slf4j,您也应该保护日志记录吗?

2022-09-01 02:22:36

帮我在这里的辩论中。:)

此处的 slf4j 站点 http://www.slf4j.org/faq.html#logging_performance 指示由于参数化日志记录,因此不需要日志记录防护。即,与其写:

if(logger.isDebugEnabled()) {
  logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
}

你可以逃脱:

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

这真的可以吗,还是会产生创建传递给 trace 方法的静态字符串的(尽管较低)成本..?


答案 1

我会试着从另一个角度来表达我的两分钱

参数化日志记录的确切好处是什么?

您只需将调用字符串串联推迟到真正需要为止,这时您确实必须记录消息。这将在禁用该特定日志记录操作时优化性能。如果不确定,请检查 SLF4J 的源代码

参数化日志记录是否使防护在所有情况下都毫无用处?

不。

在哪些情况下会使用日志记录防护装置?

当有其他潜在的昂贵操作时。

例如(在禁用此特定日志记录操作的情况下),如果我们没有日志记录防护

logger.debug("User name: {}", getUserService().getCurrentUser());
  1. 我们将从以下位置支付费用obj = getUserService().getCurrentUser()
  2. 我们将节省成本"User name: " + obj.toString()

如果我们使用日志记录防护

if (logger.isDebugEnabled()) {
    logger.debug("User: {}", getUserService().getCurrentUser());
}
  1. 我们将支付logger.isDebugEnabled()
  2. 我们将节省成本obj = getUserService().getCurrentUser()
  3. 我们将节省成本"User name: " + obj.toString()

在后一种情况下,我们将节省这两个成本,代价是在启用此特定日志记录操作时检查两次。isDebugEnabled()

注意:这只是一个例子,而不是试图在这里争论好/坏的做法。


答案 2

编写和阅读所有这些内容可能会花费与节省您一样多的时间。if(logger.isDebugEnabled()) {}

当然,调用 log 方法不是免费的,但调用 .因此,如果您使用此模式,则需要为每个处于活动状态的日志语句支付更多费用(因为日志记录框架将检查级别两次)。isDebugEnabled()

它还会使代码混乱。

在实践中,我没有发现性能损失大到足以打扰。

如果日志记录速度太慢,请编写一个非阻塞追加器,该追加器将日志事件推送到队列中,而无需进行几次检查,并使用后台线程来处理它们。

背景:标准追加器都是同步的,因此在多线程应用程序中进行日志记录可能会导致许多小的暂停,其中所有线程都等待将日志消息写入文件。


推荐