Log4j2自定义LocalLogger类异常:仅输出FATAL日志问题排查
Log4j2编程式配置日志级别失效问题排查与解决
问题描述
需求如下:
- TRACE至INFO级日志输出到
infoLog.log - WARN至FATAL级日志输出到
errorLog.log - 所有日志同时输出到控制台
采用编程式配置动态设置日志路径,但当前仅能在控制台及日志文件中看到FATAL级日志,其他级别日志无输出。
核心问题点
1. 日志路径判断逻辑完全反转
原代码中三目运算符的条件逻辑错误:
String infoLog = config != null && config.getLogFile() != null && config.getLogFile().isEmpty() ? config.getLogFile() : "infoLog.log";
这里的config.getLogFile().isEmpty()表示当配置路径为空时才使用配置值,完全不符合预期。正确逻辑应该是当配置路径不为空时才使用配置值,需要改为!config.getLogFile().isEmpty()。
2. ThresholdFilter无法满足级别范围需求
原代码使用ThresholdFilter过滤日志级别,该过滤器仅能控制">=指定级别"的日志通过,无法限定级别范围:
- InfoFile的过滤器设置为
Level.INFO,会导致WARN及以上级别日志也写入infoLog.log,违反需求 - InfoFile需要限定TRACE到INFO的范围,应使用
LevelRangeFilter
3. 根日志级别初始化存在潜在风险
原代码中Level.getLevel(logLevel)如果传入无效级别字符串会返回null,此时根日志会默认使用Level.ERROR,导致低级别日志被过滤。
修正后的完整代码
修正后的configureLogger方法
private void configureLogger() { // 修正路径判断逻辑:配置路径不为空时使用配置值,否则用默认值 String infoLog = "infoLog.log"; String errorLog = "errorLog.log"; org.apache.logging.log4j.Level rootLevel = org.apache.logging.log4j.Level.TRACE; if (config != null) { if (config.getLogFile() != null && !config.getLogFile().isEmpty()) { infoLog = config.getLogFile(); } if (config.getErrorLogFile() != null && !config.getErrorLogFile().isEmpty()) { errorLog = config.getErrorLogFile(); } if (config.getLogLevel() != null && !config.getLogLevel().isEmpty()) { org.apache.logging.log4j.Level parsedLevel = org.apache.logging.log4j.Level.getLevel(config.getLogLevel()); if (parsedLevel != null) { rootLevel = parsedLevel; } } } try (LoggerContext context = (LoggerContext) LogManager.getContext(true)) { ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder(); builder.setStatusLevel(org.apache.logging.log4j.Level.WARN); builder.setConfigurationName("DynamicConfig"); // 控制台Appender AppenderComponentBuilder consoleAppender = builder.newAppender("Console", "CONSOLE") .addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT); consoleAppender.add(builder.newLayout("PatternLayout") .addAttribute("pattern", "%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level: %msg%n")); builder.add(consoleAppender); // Info文件Appender:限定TRACE到INFO级别 AppenderComponentBuilder fileInfoAppender = builder.newAppender("InfoFile", "FILE") .addAttribute("fileName", infoLog) .addAttribute("append", "true"); fileInfoAppender.add(builder.newLayout("PatternLayout") .addAttribute("pattern", "%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level: %msg%n")); // 使用LevelRangeFilter限定级别范围 fileInfoAppender.add(builder.newFilter("LevelRangeFilter", Filter.Result.ACCEPT, Filter.Result.DENY) .addAttribute("minLevel", org.apache.logging.log4j.Level.TRACE) .addAttribute("maxLevel", org.apache.logging.log4j.Level.INFO)); builder.add(fileInfoAppender); // Error文件Appender:限定WARN到FATAL级别 AppenderComponentBuilder fileErrorAppender = builder.newAppender("ErrorFile", "FILE") .addAttribute("fileName", errorLog) .addAttribute("append", "true"); fileErrorAppender.add(builder.newLayout("PatternLayout") .addAttribute("pattern", "%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level: %msg%n")); fileErrorAppender.add(builder.newFilter("LevelRangeFilter", Filter.Result.ACCEPT, Filter.Result.DENY) .addAttribute("minLevel", org.apache.logging.log4j.Level.WARN) .addAttribute("maxLevel", org.apache.logging.log4j.Level.FATAL)); builder.add(fileErrorAppender); // 根Logger设置:使用修正后的级别,关联所有Appender RootLoggerComponentBuilder rootLogger = builder.newRootLogger(rootLevel); rootLogger.add(builder.newAppenderRef("Console")); rootLogger.add(builder.newAppenderRef("InfoFile")); rootLogger.add(builder.newAppenderRef("ErrorFile")); builder.add(rootLogger); org.apache.logging.log4j.core.config.Configuration configuration = builder.build(); context.start(configuration); } }
测试验证
运行测试类:
public class TestingMain { public static void main(String[] args) { LocalLogger logger = new LocalLogger(TestingMain.class); logger.logFinest("Trace message"); logger.logFine("Debug message"); logger.logInfo("Test info message"); logger.logWarning("Test warn message"); logger.logSevere("Test", "123", new Exception()); } }
预期效果:
- 控制台输出所有级别日志
infoLog.log中包含TRACE、DEBUG、INFO级日志errorLog.log中包含WARN、FATAL级日志
内容的提问来源于stack exchange,提问作者Julian Schaefers
相关产品推荐
相关产品推荐

