在分布式系统中,日志的查看就会变成一个比较麻烦的工作。传统上我们会把日志写在磁盘中,但是由于日志文件的轮转、切片等问题,可能会导致部分信息的遗漏,并且纯文件的日志信息交互在很多情况下会有文件占用的问题。Logback官方提供的Appender组件中有三种远程日志信息同步机制,分别是:SocketAppender、SMTPAppender、DBAppender,具体可以参考官方文档:Chapter 4: Appenders(中文版)
其中SocketAppender是纯Socket的日志信息发送组件,需要远程日志收集设备中有一个SocketServer服务;SMTPAppender是使用邮件发送日志信息的组件;DBApender可以直接将日志信息写入数据库中,表结构需要提前准备好。
但是这几种并不完全符合实际工作,所以决定自定义Appender组件。
具体参考链接如下:
SpringBoot | 第二十五章:日志管理之自定义Appender
官方源代码
经过测试,官方示例中有点问题,不能直接使用。
此次使用的spring boot版本为:2.2.5.RELEASE
代码部分
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Layout;
import ch.qos.logback.core.UnsynchronizedAppenderBase;
public class CustomizeAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
//自定义配置,需Getter和Setter方法
String printString;
//多级自定义配置,需Getter和Setter方法
ParamUnit paramUnit;
//负责将日志事件转换为字符串,需Getter和Setter方法
Layout<ILoggingEvent> layout;
@Override
public void start(){
if(this.layout==null){
System.out.println("Layout未被初始化");
}
System.out.println("自定义Appender已完成初始化");
super.start();
}
@Override
public void stop(){
//释放相关资源,如数据库连接,redis线程池等等
System.out.println("logback-stop方法被调用");
if(!isStarted()) {
return;
}
super.stop();
}
@Override
protected void append(ILoggingEvent event) {
if (event == null || !isStarted()){
System.out.println("日志事件为空或该Appender未被初始化");
return;
}
//日志事件描述语句包含有换行符
System.out.print(printString + ":" + layout.doLayout(event));
System.out.println(paramUnit.param1+" "+paramUnit.param2);
}
public Layout<ILoggingEvent> getLayout() {
return layout;
}
public void setLayout(Layout<ILoggingEvent> layout) {
this.layout = layout;
}
public String getPrintString() {
return printString;
}
public void setPrintString(String printString) {
this.printString = printString;
}
public ParamUnit getParamUnit() {
return paramUnit;
}
public void setParamUnit(ParamUnit paramUnit) {
this.paramUnit = paramUnit;
}
}
多级配置参数Unit类
public class ParamUnit {
String param1;
String param2;
public String getParam1() {
return param1;
}
public String getParam2() {
return param2;
}
public void setParam1(String param1) {
this.param1 = param1;
}
public void setParam2(String param2) {
this.param2 = param2;
}
}
配置部分
<?xml version="1.0" encoding="UTF-8"?>
<!--用于支持日志文件个性化配置-->
<configuration scan="true" debug="true">
<contextName>logback</contextName>
<property name="log.path" value="log/springboot.log"></property>
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH-mm-ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!--输出到文件-->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>log/springboot.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>10</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd} %d{HH-mm-ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!--class:自定义的Appender路径-->
<appender name="CustomizeAppender " class="com.demo.LogbackAppender.CustomizeAppender ">
<layout>
<pattern>%date [%thread] %-5level %logger - %msg%n</pattern>
</layout>
<printString>test</printString>
<paramUnit>
<param1>param1test</param1>
<param2>param2test</param2>
</paramUnit>
</appender>
<root level="info">
<appender-ref ref="console" />
<appender-ref ref="file" />
<appender-ref ref="CustomizeAppender " />
</root>
</configuration>