详解Spring Boot下使用logback 记录多个文件日志

网友投稿 570 2023-01-23


详解Spring Boot下使用logback 记录多个文件日志

背景

这两天遇到一个比较有意思的日志问题.

近期对我之前的python代码进行java的重构, 一方面是因为java使用的医疗库非常健全稳定, 可以商用. 另一方面是因为java速度快, 这个库的实现的效率也高, 性能是Python版本的好几倍.

说道多文件日志, 它的优点是每个日志只容纳自身的逻辑, 所以对于一般的入门开发者或者是初级运维工程师查看起来非常方便.

初步尝试

因为spring boot的配置一般来讲是application.properties, 但是同时开发者可以使用yml格式的配置, 二者相比, yml文件更为简洁. 熟读python之禅的我当然是简洁胜于冗余选择了yml.

发现spring-boot可以通过application.yml配置日志. 高兴的配置一番之后发现没法配置多个logger, 弃用! 改用logback-spring.xml(为什么不用logback.xml? 因为-spring这种文件可以获取到spring配置中的变量.下面再说)

第一次实现

我有好几个服务需要打日志. 一般来讲我的日志风格是 *.log 保存 INFO以上级别日志. *.err.log保存ERROR以上级别日志. 我如果每个文件日志都使用一个Appender的话, 配置文件太长了. 而且很难看, 不是我的风格.

Google了一下, 发现了这种方案:

# 下面这一行的意思是使用application.yml中的global.log-dir变量

# 这个是一个可以定义变量的Appender

# 使用 LoggerNameBasedDiscriminator 这个类根据当前Logger获取变量

general

# 根据变量loggerName名字生成根据日期滚动的Appender

${LOG_DIR}/${loggerName}.log

${LOG_DIR}/${loggerName}.%d{yyyy-MM-dd}.log.gz

15

INFO

%d{HH:mm:ss.SSS} %-5level - %msg%n

${LOG_DIR}/${loggerName}.err.log

${LOG_DIR}/${loggerName}.%d{yyyy-MM-dd}.err.log.gz

15

ERROR

%d{HH:mm:ss.SSS} %-5level - %msg%n

下的是对应的 LoggerNameBasedDiscriminator 类

package com.utils.loggers;

import ch.qos.logback.classic.spi.ILoggingEvent;

import ch.qos.logback.core.sift.AbstractDiscriminator;

public class LoggerNameBasedDiscriminator extends AbstractDiscriminator {

private static final String KEY = "loggerName";

private String defaultValue;

public String getDefaultValue() {

return defaultValue;

}

public void setDefaultValue(String defaultValue) {

this.defaultValue = defaultValue;

}

# 这就是之所以xml里面可以引用loggerName变量的原因

public String getKey() {

return KEY;

}

public void setKey() {

throw new UnsupportedOperationException("Key not settable. Using " + KEY);

}

public String getDiscriminatingValue(ILoggingEvent e) {

String loggerName = e.getLoggerName();

if (loggerName == null)

return defaultValue;

else {

String[] split = loggerName.split("\\.");

return split[split.length - 1];

}

}

}

最开始我的日志里面没有报错信息, 正常的生成INFO日志. 但是后来发现事情好像不是想象的那样

问题出现

后来我把程序改成多线程. 发现所有涉及到多线程的服务日志里面都没信息了. Google半天, 发现几个令我震惊的真相:

真相1: 所有滚动Appender都不支持异步追加 (其实也不是, 但是那种方式需要写死日志文件名, 不推荐, 不讲)

真相2: SiftingAppender 内部最多嵌套一个Appender. 所以理论上我的ERROR的日志里面应该永远不会有内容.

问题解决

对于之前的两个问题, 分而治之.

不支持异步

再次谷歌(到这里读者基本上发现了我搬砖的本质), 发现有个Appender名字叫AsyncAppender, 这玩意是一个其他Appender的Wrapper. 说白了, 就是你打日志的命令是异步的, 放到队列里面, 而它真正的打日志的动作是一个单独的同步线程. 这就牛逼了, 使用这玩意收集我所有日志, 然后再转发给SiftingAppender 进行分发即可.

SiftingAppender 内部最多嵌套一个Appender

这个好办, 把INFO的Appender和ERROR的Appender拆开放到两个SiftingAppender里面就行了, 不过这样的话, 前面提到的的AsyncAppender 也要写两个.

最后, logback-spring.xml文件如下

class="ch.qos.logback.core.rolling.RollingFileAppender">

${LOG_DIR}/${loggerName}.log

class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

${LOG_DIR}/${loggerName}.%d{yyyy-MM-dd}.log

15

INFO

%d{HH:mm:ss.SSS} %-5level - %msg%n

class="ch.qos.logback.core.rolling.RollingFileAppender">

${LOG_DIR}/${loggerName}.log

class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

${LOG_DIR}/${loggerName}.%d{yyyy-MM-dd}.log

15

INFO

%d{HH:mm:ss.SSS} %-5level - %msg%n

class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

${LOG_DIR}/${loggerName}.%d{yyyy-MM-dd}.log

15

INFO

%d{HH:mm:ss.SSS} %-5level - %msg%n

${LOG_DIR}/${loggerName}.err.log

${LOG_DIR}/${loggerName}.%d{yyyy-MM-dd}.err.log

15

50MB

ERROR

%d{HH:mm:ss.SSS} %-5level - %msg%n

0

512

0

512


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:详解Java数字签名提供XML安全
下一篇:Java网络编程之TCP程序设计
相关文章

 发表评论

暂时没有评论,来抢沙发吧~