背景
在维护一个旧项目,忽然间看到服务输出的日志文件中的debug.log,里面的内容和info.log完全一致。
复现 & 排查
xml文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false" scanPeriod="30 seconds" debug="false">
<contextName>app-xxx</contextName>
<!--服务端日志目录-->
<property name="log.path" value="/var/log/app-xxx/log"/>
<property name="log.charset" value="utf-8"/>
<property name="log.pattern"
value="%contextName %red(%d{yyyy-MM-dd HH:mm:ss}) [%X{traceId}/%X{spanId}] %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %msg%n"/>
<!-- Log file info output -->
<appender name="info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/%d{yyyy-MM, aux}/info.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>90</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date [%thread] %-5level [%X{traceId}/%X{spanId}] [%logger{50}] %file:%line - %msg%n</pattern>
<charset>${log.charset}</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
</appender>
<!-- Log file debug output -->
<appender name="debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/debug.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/%d{yyyy-MM, aux}/debug.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>90</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date [%thread] %-5level [%X{traceId}/%X{spanId}] [%logger{50}] %file:%line - %msg%n</pattern>
<charset>${log.charset}</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
</appender>
<!-- Log file error output -->
<appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/%d{yyyy-MM, aux}/error.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>90</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date [%thread] %-5level [%X{traceId}/%X{spanId}] [%logger{50}] %file:%line - %msg%n</pattern>
<charset>${log.charset}</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
<!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 -->
<root level="INFO">
<appender-ref ref="info"/>
</root>
<root level="ERROR">
<appender-ref ref="error"/>
</root>
<root level="DEBUG">
<appender-ref ref="debug"/>
</root>
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
<charset>${log.charset}</charset>
</encoder>
</appender>
<!--普通日志输出到控制台-->
<root level="info">
<appender-ref ref="console"/>
</root>
</configuration>
问题出现在多个root节点。
<root level="INFO">
<appender-ref ref="info"/>
</root>
<root level="ERROR">
<appender-ref ref="error"/>
</root>
<root level="DEBUG">
<appender-ref ref="debug"/>
</root>
<root level="info">
<appender-ref ref="console"/>
</root>此时新建一个类(和启动类同包),如下
package com.app.xxx;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class LoggerTest implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
log.debug("debug11111111111111111111");
log.info("info111111111111111111111");
log.warn("warn1111111111111111111111");
log.error("error1111111111111111111111111111111");
}
}
启动时发现debug.log和info.log里都是只有info111111111111111111111/warn1111111111111111111111/error1111111111111111111111111111111,也都没有debug11111111111111111111。
问了ai,说明logback会只使用最后一个root节点,也有说是合并多个root的子节点,按我运行的结果来看,上面多个root节点相当于如下
<root level="INFO">
<appender-ref ref="info"/>
<appender-ref ref="error"/>
<appender-ref ref="debug"/>
<appender-ref ref="console"/>
</root>即以最后一个root节点为准(取其level),把其它root节点的子节点合并过来。
测试时把多个root节点中的 level=DEBUG移到最后一位。即
<root level="ERROR">
<appender-ref ref="error"/>
</root>
<root level="INFO">
<appender-ref ref="info"/>
</root>
<root level="info">
<appender-ref ref="console"/>
</root>
<root level="DEBUG">
<appender-ref ref="debug"/>
</root>会发现debug.log中打印了很多日志,而info.log很少,且debug11111111111111111111出现在debug.log中,不在info.log中。
解决问题
该服务不需要打印debug日志。
修正后的xml如下。只使用info.log(打印info/warn/error级别的日志),error.log(打印error级别日志)
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false" scanPeriod="30 seconds" debug="false">
<contextName>app-xxx</contextName>
<!--服务端日志目录-->
<property name="log.path" value="/var/log/app-xxx/log"/>
<property name="log.charset" value="utf-8"/>
<property name="console.log.pattern"
value="%contextName %red(%d{yyyy-MM-dd HH:mm:ss}) [%X{traceId}/%X{spanId}] %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %msg%n"
/>
<appender name="infoAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/%d{yyyy-MM, aux}/info.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>90</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date [%thread] %-5level [%X{traceId}/%X{spanId}] [%logger{50}] - %msg%n</pattern>
<charset>${log.charset}</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
</appender>
<appender name="errorAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/%d{yyyy-MM, aux}/error.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>90</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date [%thread] %-5level [%X{traceId}/%X{spanId}] [%logger{50}] - %msg%n</pattern>
<charset>${log.charset}</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${console.log.pattern}</pattern>
<charset>${log.charset}</charset>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="infoAppender"/>
<appender-ref ref="errorAppender"/>
<appender-ref ref="consoleAppender"/>
</root>
</configuration>
作者:张三 创建时间:2025-12-11 14:13
最后编辑:张三 更新时间:2025-12-11 15:36
最后编辑:张三 更新时间:2025-12-11 15:36