SpringBoot多环境下多个logback配置文件生效问题踩坑
问题发现背景
小编在工作项目中分别配置了dev,test,prod三个环境的配置文件和对应的logback配置文件
但是在项目上生成环境的的中途,突然发现多生成了一份test的日志文件,再检查dev和test环境,发现除了test环境正常以外,dev和生产环境都生成了两份日志文件,以dev环境为例
排查问题
1. 检查配置YML文件
检查发现yml配置文件无误
2. 检查logback配置文件
logback-dev.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<!--应用名称-->
<property name="APP_NAME" value="websocket-service"/>
<!--日志文件保存路径-->
<property name="LOG_FILE_PATH" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/logs}"/>
<contextName>${APP_NAME}</contextName>
<!--每天记录日志到文件appender-->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE_PATH}/${APP_NAME}-dev-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxHistory>3</maxHistory>
<MaxFileSize>30MB</MaxFileSize>
<totalSizeCap>5000MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- 单独的错误日志输出配置,按照每天生成日志文件 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<fileNamePattern>${LOG_FILE_PATH}/${APP_NAME}-dev-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志文件保留天数-->
<maxHistory>3</maxHistory>
<!--单日志文件的大小-->
<maxFileSize>30MB</maxFileSize>
<!-- <!–总日志量大小,实际产生的文件个数=totalSizeCap/maxFileSize–>
<totalSizeCap>300MB</totalSizeCap>-->
<totalSizeCap>5000MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
<!--输出到logstash的appender-->
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<!--可以访问的logstash日志收集端口-->
<destination>logstash.logging:4560</destination>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
<customFields>{"serverName":"${APP_NAME}-dev"}</customFields>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="ERROR_FILE"/>
<appender-ref ref="LOGSTASH" />
</root>
</configuration>
依旧无误
那么问题在哪里呢?寻常手段,网上查询也无果,只有靠自己了有深入源码
源码排查思路
1. 排查logback加载了那些配置文件,启动项目,发现确实加载了test的配置文件
2. 源码断点,发现问题
日志输出的提示,很快的反向找到了logback加载配置文件的关键类 ch.qos.logback.core.joran.GenericConfigurator#doConfigure 方法
发现第一个进来的url就是test,只有在往上寻找url的来源
发现往上一层ch.qos.logback.classic.util.ContextInitializer#configureByResource 方法也是接收的url参数没有找到,继续往上
当找到 ch.qos.logback.classic.util.ContextInitializer#autoConfig 方法的时候终于发现了 URL的来源
进入 findURLOfDefaultConfigurationFile 方法发现了 TEST_AUTOCONFIG_FILE,GROOVY_AUTOCONFIG_FILE,AUTOCONFIG_FILE 三个静态变量
分别对应的值如下
这句代码
final public static String TEST_AUTOCONFIG_FILE = "logback-test.xml";
这下破案了,并不是配置没有生效,而是logback配置文件加载顺序的问题,不管我们有没有配置都会默认去加载 logback-test.xml 这个配置文件,这也很好地解释为啥test环境是正常的,不会出现其他环境的日志配置.
3.解决方式
- 修改自己的 logback-test.xml 配置文件的名称,如 logback-etest.xml
- 在程序打包的时候只将对应环境的配置文件进行打包,而不是所有的配置文件都打包进去(推荐方法)
小结
虽然问题不算复杂,如果小编早点是用解决方式2进行打包,就不会出现这个问题,但是在日常开发中往往是这种不报错,也不明所以的问题成为我们的拦路虎,所以分享出来,为以后出现类似问题的小伙伴提供一种解决思路!希望对各位有用!