背景
项目中有个节点健康检查扫描功能,每10秒扫描一次节点。
如果节点挂掉,会输出健康检查失败的日志。
测试环境,虽然配置了多个节点,但并没有都启动,所以在扫描的时候,会不断的出现报错,
对于排查日志来说,神烦。
但是节点挂掉的这个日志又不能不输出,否则正式环境要是真挂了,看不出来就很麻烦了。
所以最好的方案是这个健康检查失败的日志,能够单独输出,比如单独输出到指定文件,这样既不影响看日志,又保留了健康检查失败的日志。
解决方案
在application.yml里面,有logging配置,本来想着能不能直接在这里配出单独输出的效果,查了很多资料之后,表示没戏。
然后采用配置logback-spring.xml的方式来实现:
- 在application.yml同级目录新建logback-spring.xml
- 写入以下内容
<configuration><include resource="org/springframework/boot/logging/logback/defaults.xml" /><appender name="healthCheck" class="ch.qos.logback.core.FileAppender"><file>D:\fy\log\healthCheck.log</file><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${CONSOLE_LOG_PATTERN}</pattern><charset>${CONSOLE_LOG_CHARSET}</charset></encoder></appender><logger name="healthCheckLog" level="info" additivity="false"><appender-ref ref="healthCheck" /></logger><root level="INFO"><appender-ref ref="CONSOLE" /></root>
</configuration>
- 在健康检查的java类中,加入以下代码
//这里的healthCheckLog对应logback-spring.xml中<logger name="healthCheckLog" >的这个logger
private static Logger healthCheckLog = LoggerFactory.getLogger("healthCheckLog");
//在需要输出日志的地方,用这个healthCheckLog来输出日志,就可以了
healthCheckLog.error("执行器{}健康检查失败:{}",exe.customGetUrl(),e.getMessage());
- 重启服务,完事
解决过程
解决的过程其实没有那么顺利,一开始仅配置了
<configuration><appender name="healthCheck" class="ch.qos.logback.core.FileAppender"><file>D:\fy\log\healthCheck.log</file><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><logger name="healthCheckLog" level="info" additivity="false"><appender-ref ref="healthCheck" /></logger><root level="INFO"><appender-ref ref="CONSOLE" /></root>
</configuration>
结果发现服务起不来,报Could not find an appender named [CONSOLE]. Did you define it below instead of above in the configuration file?
这个是因为启动的时候,它会扫描<root level=“INFO”>里面的<appender-ref ref=“CONSOLE” />,我这里写了一个<appender-ref ref=“CONSOLE” />,但是logback-spring.xml中却没有配置CONSOLE相关的appender,所以它就报错了。
然后,我补上了\ ,然后去指定了输出格式(输出格式其实不是我想指定的,而是它强制要求我要指定的,没办法,拿gpt生成了一个)。不过看着格式挺整齐的,但却没有了颜色。在我配置之前,springboot默认的可是有彩色的,比黑白的好看多了。
然后我在网络上查到了可以用%clr()这种方式给日志加上颜色,像这样:
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n</pattern></encoder></appender>
结果启动的时候报:Failed to create converter for [%clr] keyword
大概意思就是它不知道%clr是什么意思,%clr其实是一个自定义的日志格式解析器,springboot有默认的实现。但由于我们自己写了配置,导致它不认spring的,只认我们的。
spring既然已经写了实现,用不起来就太可惜了,后来查了多方资料,才了解到可以这么写
<!-- 在头部引用spring的默认实现xml--><include resource="org/springframework/boot/logging/logback/defaults.xml" /><!--然后就可以用里面写好的格式--><pattern>${CONSOLE_LOG_PATTERN}</pattern><charset>${CONSOLE_LOG_CHARSET}</charset>
至此,问题完美解决
原理
spring默认会扫描application.yml目录下的所有文件,所以,只要你的文件名对,在这个目录下新建的文件就会发挥作用,因此,虽然原来没有logback-spring.xml这文件,我直接新建之后,就起效了。
logback-spring.xml这个文件其实是对application.yml里面logging配置的补充,可以理解为logging是简单配置,logback-spring.xml是高级配置。
另外还有一个配置,logback.xml,也会生效,但是据说这两个的差别是logback.xml在spring初始化之前加载,logback-spring.xml在spring初始化后加载,所以logback-spring.xml能用的东西会更多一点。