如何在Log4j 1.x与Log4j 2中输出小写的日志事件级别?
Log4j 1.x与2.x输出小写日志级别的解决方案
嘿,针对你问的两个Log4j版本输出小写日志级别的问题,我来给你梳理下具体的实现方式:
Log4j 1.2 打印小写事件级别
Log4j 1.2本身没有原生支持直接输出小写的日志级别,得靠自定义扩展来实现,最靠谱的方式是写一个自定义的日志模式转换器:
- 首先创建一个转换器类,继承Log4j的
PatternConverter,重写convert方法把级别转成小写:
import org.apache.log4j.helpers.PatternConverter; import org.apache.log4j.spi.LoggingEvent; public class LowercaseLevelConverter extends PatternConverter { @Override protected String convert(LoggingEvent event) { // 把日志级别字符串转成全小写 return event.getLevel().toString().toLowerCase(); } }
- 接着创建一个自定义的
PatternLayout,注册刚才的转换器,让Log4j能识别我们的自定义模式标记:
import org.apache.log4j.PatternLayout; import org.apache.log4j.helpers.PatternParser; public class CustomLowercaseLayout extends PatternLayout { @Override protected PatternParser createPatternParser(String pattern) { PatternParser parser = super.createPatternParser(pattern); // 注册自定义转换器,用小写的'l'作为模式标记(比如%l) parser.addConverter('l', LowercaseLevelConverter.class); return parser; } }
- 最后在你的
log4j.properties配置文件里使用这个自定义布局,用%l代替原来的%p来输出小写级别:
# 配置控制台输出 log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=com.yourpackage.CustomLowercaseLayout # 这里的%l就是我们自定义的小写级别标记 log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %l %c{1} - %m%n
如果不想写代码,也可以在业务代码里封装日志工具类,手动把级别转小写后输出,但这种方式耦合性高,不推荐。
Log4j 2.x 输出小写日志级别
Log4j 2.x原生就支持这个需求,而且有多种实现方式,非常灵活:
方式1:直接使用%level的lowerCase参数
这是最简单的方式,直接在模式字符串里给%level加上lowerCase=true参数即可:
<!-- 示例log4j2.xml配置 --> <Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{ISO8601} %level{lowerCase=true} %c{1} - %m%n"/> </Console> </Appenders> <Loggers> <Root level="debug"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration>
这样输出的级别就是debug、info、warn、error这类全小写格式。
方式2:使用%replace函数做字符串替换
如果需要更灵活的字符串处理(比如只转部分字符),可以用Log4j 2的%replace函数:
<PatternLayout pattern="%d{ISO8601} %replace{%level}{[A-Z]+}{$0.toLowerCase()} %c{1} - %m%n"/>
这个正则会把级别字符串里的所有大写字母转成小写,效果和方式1一致。
方式3:自定义级别渲染器(进阶)
如果有特殊的级别格式需求(比如自定义级别名称),可以实现LevelPatternConverter的子类来自定义渲染逻辑,但一般情况下原生参数已经完全够用,没必要折腾这个。
内容的提问来源于stack exchange,提问作者Micahel




