如何在Log4j2 Core的PatternLayout中自定义裁剪日志记录器名称?
Log4j2 PatternLayout 裁剪日志记录器名称的解决方案
针对你需要将com.test1.test2.test3.test4.test5.ClassName格式化为c.t.t.t.t.test5.ClassName的需求,官方默认的PatternLayout确实只支持从末尾裁剪,以下是几个可行的实现方案:
方法一:自定义PatternConverter
这是最灵活的方案,通过扩展Log4j2的PatternConverter来实现自定义的名称裁剪逻辑:
- 实现自定义转换器类:
import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.pattern.ConverterKeys; import org.apache.logging.log4j.core.pattern.LogEventPatternConverter; @ConverterKeys({"customLogger"}) // 自定义转换器的标识 public class CustomLoggerNameConverter extends LogEventPatternConverter { protected CustomLoggerNameConverter(String[] options) { super("CustomLogger", "customLogger"); } public static CustomLoggerNameConverter newInstance(String[] options) { return new CustomLoggerNameConverter(options); } @Override public void format(LogEvent event, StringBuilder toAppendTo) { String loggerName = event.getLoggerName(); if (loggerName == null || loggerName.isEmpty()) { toAppendTo.append("root"); return; } String[] parts = loggerName.split("\\."); StringBuilder sb = new StringBuilder(); // 处理前n-2个部分,取首字母 for (int i = 0; i < parts.length - 2; i++) { if (parts[i].length() > 0) { sb.append(parts[i].charAt(0)).append("."); } } // 添加最后两个部分(包名+类名) sb.append(parts[parts.length - 2]).append(".").append(parts[parts.length - 1]); toAppendTo.append(sb); } }
- 在Log4j2配置文件中注册并使用该转换器:
<Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%customLogger %msg%n"/> </Console> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration>
方法二:使用ScriptPatternSelector结合脚本处理
利用Log4j2的ScriptPatternSelector功能,通过脚本动态处理日志记录器名称,无需编写Java类:
<Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout> <ScriptPatternSelector defaultPattern="%logger %msg%n"> <Script name="CustomLoggerPattern" language="Groovy"><![CDATA[ def loggerName = logEvent.getLoggerName(); if (!loggerName) return defaultPattern; def parts = loggerName.split("\\."); def sb = new StringBuilder(); for (int i = 0; i < parts.length - 2; i++) { if (parts[i].length() > 0) { sb.append(parts[i].charAt(0)).append("."); } } sb.append(parts[parts.length - 2]).append(".").append(parts[parts.length - 1]); return sb.toString() + " %msg%n"; ]]></Script> </ScriptPatternSelector> </PatternLayout> </Console> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration>
方法三:代码层面自定义Logger(可选)
如果可以在代码中调整日志获取逻辑,也可以提前处理日志记录器名称:
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class CustomLogger { public static Logger getLogger(Class<?> clazz) { String originalName = clazz.getName(); String[] parts = originalName.split("\\."); StringBuilder sb = new StringBuilder(); for (int i = 0; i < parts.length - 2; i++) { if (parts[i].length() > 0) { sb.append(parts[i].charAt(0)).append("."); } } sb.append(parts[parts.length - 2]).append(".").append(parts[parts.length - 1]); return LogManager.getLogger(sb.toString()); } }
使用时直接调用CustomLogger.getLogger(YourClass.class)即可,后续日志输出的记录器名称就是处理后的格式。
内容的提问来源于stack exchange,提问作者manu
相关产品推荐
相关产品推荐

