代码改变世界

log4j2异步日志配置及官方文档的问题澄清

2019-06-02 19:50  chen.simon  阅读(4538)  评论(0编辑  收藏  举报

配置及demo

方法一全部打开

加启动参数 -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
启动参数的这个key有点说法:
按官方文档说明http://logging.apache.org/log4j/2.x/manual/async.html#AllAsync key是-Dlog4j2.contextSelector=...
但是你如果亲自做实验,或亲自使用过,可能就会发现问题,简单的说跟你使用的版本有关:
-DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector // 全版本支持
-Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector // 2.10.0以后版本支持
仔细看官方文档上有一句

Note that system properties were renamed into a more consistent style in Log4j 2.10.0. All old property names are still supported which are documented here.

相关代码(2.10.0以后版本):
参见 org.apache.logging.log4j.util.PropertiesPropertySource 和
org.apache.logging.log4j.util.PropertiesUtil.Environment
Environment中有三组配置数据,key不同,业务语义相同:

literal
{java.runtime.name=Java(TM) SE Runtime Environment}


normalized
{log4j2.javaRuntimeName=Java(TM) SE Runtime Environment} key 是log4j2.前缀 加上驼峰形式变量

tokenized
{[java, runtime, name]=Java(TM) SE Runtime Environment}  key是list

方法二同步异步混合

<!-- 使用异步日志时,启用如下配置,异步配置默认不打印location。此种方法无需配置JVM启动参数。 -->
<asyncRoot level="debug">
	<AppenderRef ref="Console" />
</asyncRoot>

一些说明

  • 默认不打印location信息,诸如代码行号,类,方法等。 如果需要的话需要加上includeLocation="true",但是按官方说法会慢30-100倍。
  • 异步的时候,如果在真正打印日志时,日志信息中所引用的对象中的字段值发生了改变,比如"hello {}", user.name这种。会不会影响打印日志的准确性。答案是不会,因为log4j做了snapshot机制。

异步日志的弊端

异步日志不是只有优点没有弊端的,官方给出了一些不使用的场景(Drawbacks):

  • 异常处理。即使有异常处理器,也不能覆盖所有的案例。
  • 在一些使用了诸如 MapMessage 和 StructuredDataMessage 这种没法通过snapshot规避异步打印时日志信息可能变化的问题
  • 在CPU很少的环境,比如就1个CPU
  • 打印日志的速度远远超过appender的吞吐。此时异步并不能解决问题,需要用更快的appender。