log4j:踩坑记录:log4j2异步日志无法打印%L %M等位置信息

问题描述:

    最近项目想打印更详细的日志信息,包括打印日志的位置和方法。在log4j2的配置文件中为格式添加%L和%M后,发现并不能打印出行号和方法名。

    不了解log4j2配置文件请参考log4j2配置文件解析。

问题分析:

    一通乱七八糟的操作后,毫无用处,还是乖乖的去看官方文档吧。由于配置文件使用的是PatternLayout,所以在官网找到PatternLayout,找到对L属性的描述:

    貌似还有更详细的介绍。点蓝色的链接(官网链接:LocationInformation),可以看到在Location Information中有如下描述:

If one of the layouts is configured with a location-related attribute like HTML locationInfo, or one of the patterns %C or %class, %F or %file, %l or %location, %L or %line, %M or %method, Log4j will take a snapshot of the stack, and walk the stack trace to find the location information.

This is an expensive operation: 1.3 - 5 times slower for synchronous loggers. Synchronous loggers wait as long as possible before they take this stack snapshot. If no location is required, the snapshot will never be taken.

However, asynchronous loggers need to make this decision before passing the log message to another thread; the location information will be lost after that point. The performance impact of taking a stack trace snapshot is even higher for asynchronous loggers: logging with location is 30-100 times slower than without location. For this reason, asynchronous loggers and asynchronous appenders do not include location information by default.

You can override the default behaviour in your logger or asynchronous appender configuration by specifying includeLocation="true".

    上述信息中的重点:

    1) 位置信息包括:%C or %class, %F or %file, %l or %location, %L or %line, %M or %method

    2)如果配置中包含位置信息,log4j会生成一个镜像,用于定位;

    3)同步日志会先等待镜像的生成,然后再去打印日志。这会导致比没有位置信息慢上1.3到5倍;

    4)由于异步日志会把日志信息传递给另一个线程,所以如果异步日志想要打印位置信息,需要提前决定,否则无法打印;

    5)异步日志的提前决定,通过配置includeLocation="true"来实现;

    6)异步日志打印log,会导致比不打印log慢30到100倍。

解决方案:

    根据上面的分析可以知道,配置includeLocation="true"可以使异步日志打印位置信息。那么:

    情况1:对于properties配置文件,添加如下配置:

rootLogger.includeLocation=true

    情况2:对于xml配置文件,添加如下配置:


  
    
  

总结:

    在配置文件的日志格式中配置位置信息( %C or %class, %F or %file, %l or %location, %L or %line, %M or %method)后,同步日志可以直接打印位置信息,而异步日志则必须配置includeLocation="true"才能打印位置信息。同时打印位置信息会产生很大的开销,尤其对于异步日志的性能影响很大。

你可能感兴趣的:(架构工具)