如何为Log4j添加微秒级日志?自定义格式器及Log4j2问题排查
Log4j(含Log4j2)微秒级日志配置及问题解决
一、Log4j 1.x 实现微秒级日志输出
如果用的是Log4j 1.x版本,官方默认格式器不支持微秒输出,得自己动手写个自定义格式器来实现:
1. 自定义微秒转换器
先写一个PatternConverter子类,用来获取并格式化微秒部分:
import org.apache.log4j.pattern.PatternConverter; import org.apache.log4j.spi.LoggingEvent; public class MicrosecondPatternConverter extends PatternConverter { @Override protected String convert(LoggingEvent event) { // 从日志事件的毫秒时间戳,结合当前纳秒计算真实微秒 long timestampMillis = event.getTimeStamp(); long currentNanos = System.nanoTime(); // 计算当前毫秒内的微秒数:(纳秒 % 1000000) 就是当前毫秒的微秒部分 long microsInMillis = (currentNanos % 1000000); // 组合成完整的6位微秒(毫秒转微秒 + 当前毫秒内的微秒) long totalMicros = (timestampMillis % 1000) * 1000 + microsInMillis; return String.format("%06d", totalMicros); } // 提供实例创建方法,供Log4j调用 public static MicrosecondPatternConverter newInstance(String[] options) { return new MicrosecondPatternConverter(); } }
2. 自定义PatternLayout
把上面的转换器注册到自定义Layout里,让Log4j识别新的转换符(比如用%m表示微秒):
import org.apache.log4j.PatternLayout; public class MicrosecondPatternLayout extends PatternLayout { public MicrosecondPatternLayout() { super(); // 注册转换器,关联转换符'm' addConverter('m', MicrosecondPatternConverter.class); } public MicrosecondPatternLayout(String pattern) { super(pattern); addConverter('m', MicrosecondPatternConverter.class); } }
3. 配置文件使用
在log4j.properties里配置这个自定义Layout:
log4j.rootLogger=DEBUG, console log4j.appender.console=org.apache.log4j.ConsoleAppender # 指定我们自己写的Layout类路径 log4j.appender.console.layout=com.yourpackage.MicrosecondPatternLayout # 转换规则里用%d{HH:mm:ss,SSS}输出毫秒,加.%m输出微秒 log4j.appender.console.layout.ConversionPattern=%d{HH:mm:ss,SSS}.%m [%t] %-5level %logger{36} - %msg%n
这样输出的日志时间就会是类似12:42:05,972.123456的格式,包含完整的微秒信息。
二、Log4j2 微秒输出固定值的问题解决
你遇到的%d{ABSOLUTE_NANOS}输出微秒纳秒始终是803200的问题,其实是因为这个格式符的设计缺陷——它根本没获取真实的纳秒时间,只是在毫秒时间后面硬拼了固定后缀,完全是个坑!
正确的Log4j2微秒配置方式
Log4j2本身支持直接通过自定义日期格式输出微秒,不用依赖那个有问题的ABSOLUTE_NANOS。修改你的log4j2.xml配置:
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="INFO"> <Appenders> <Console name="console" target="SYSTEM_OUT"> <!-- 用自定义日期格式,SSS是毫秒,后面加6位S表示微秒 --> <PatternLayout pattern="%d{HH:mm:ss,SSSSSS} [%t] %-5level %logger{36} - %msg%n"/> <!-- 如果需要纳秒,可以写成%{HH:mm:ss,SSSSSSSSS},9位S就是纳秒 --> </Console> </Appenders> <Loggers> <Root level="debug" additivity="false"> <AppenderRef ref="console" /> </Root> </Loggers> </Configuration>
这样配置后,输出的时间就会是真实的微秒/纳秒值,不会再出现固定后缀的问题了。
另外,如果你需要ISO8601格式带微秒的时间,也可以用:
<PatternLayout pattern="%d{yyyy-MM-dd'T'HH:mm:ss.SSSSSS} [%t] %-5level %logger{36} - %msg%n"/>
内容的提问来源于stack exchange,提问作者Chetna rustagi
相关产品推荐
相关产品推荐

