通過擴(kuò)展logback日志來發(fā)送異常信息郵件
系統(tǒng)異常了,上篇是通過在全局異常中通過調(diào)用發(fā)送郵件的處理器代碼進(jìn)行郵件的發(fā)送,總是覺得還不那么優(yōu)雅
這篇是通過擴(kuò)展 logback 的日志插件來處理 err 級(jí)別的日志異常信息來發(fā)送郵件的
通過這篇的學(xué)習(xí),可以掌握如何擴(kuò)展 logback 的日志類,來實(shí)現(xiàn)自己不可告人的目的
下面直接上代碼
首先自定義一個(gè)日志處理處理類 wlcLogLogbackAppender
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.classic.spi.ThrowableProxy;
import ch.qos.logback.core.AppenderBase;
import com.handler.WlcAsyncHandler;
import com.utils.SpringContextUtil;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
/**
* 描述: 自定義日志處理類 <br>
* 時(shí)間: 2021-07-01 11:11 <br>
* 作者:IT學(xué)習(xí)道場(chǎng)
*/
public class wlcLogLogbackAppender extends AppenderBase<LoggingEvent> {
@Override
protected void append(LoggingEvent eventObject) {
if(eventObject instanceof LoggingEvent){
LoggingEvent loggingEvent = (LoggingEvent)eventObject;
//拿到ThrowableProxy
ThrowableProxy throwableProxy = (ThrowableProxy) loggingEvent.getThrowableProxy();
if (Objects.nonNull(throwableProxy)) {
//獲取 throwable 頂級(jí)異常
Throwable throwable = throwableProxy.getThrowable();
//獲取log的msg
String formattedMessage = loggingEvent.getFormattedMessage();
//獲取請(qǐng)求request
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes()).getRequest();
//獲取spring的spring.mail.enable屬性值,下面的邏輯你也可以自己根據(jù)想法自己玩也行
String mailEnableProperty = SpringContextUtil.getEnvironmentProperty("spring.mail.enable");
mailEnableProperty = (mailEnableProperty == null) ? "false" : mailEnableProperty;
boolean mailEnable = Boolean.valueOf(mailEnableProperty);
if (mailEnable){
//獲取郵件的處理類
WlcAsyncHandler emailHandler = SpringContextUtil.getBean(WlcAsyncHandler.class);
emailHandler.handle(formattedMessage, throwable, request);
}
}
}
super.doAppend(eventObject);
}
}
自定義的日志處理類搞完了,剩下的就是在logback-spring.xml中配置下就行,配置級(jí)別是 error 級(jí)別
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 修改一下路徑-->
<property name="PATH" value="./log"></property>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) %blue(%-50logger{50}:%-4line) %thread %green(%-18X{LOG_ID}) %msg%n</Pattern>-->
<Pattern>%d{ss.SSS} %highlight(%-5level) %blue(%-30logger{30}:%-4line) %thread %green(%-18X{LOG_ID}) %msg%n</Pattern>
</encoder>
</appender>
<appender name="TRACE_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${PATH}/trace/trace.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${PATH}/trace/trace.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--因?yàn)?FileNamePattern 配置規(guī)則是yyyy-MM-dd,就是天,所以maxHistory代表多少天-->
<cleanHistoryOnStart>true</cleanHistoryOnStart>
<!--maxHistory生效必須加 <cleanHistoryOnStart>true</cleanHistoryOnStart>-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<layout>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %-50logger{50}:%-4line %green(%-18X{LOG_ID}) %msg%n</pattern>
</layout>
</appender>
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${PATH}/error/error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${PATH}/error/error.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
<maxHistory>15</maxHistory>
</rollingPolicy>
<layout>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %-50logger{50}:%-4line %green(%-18X{LOG_ID}) %msg%n</pattern>
</layout>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--配置自定義的日志處理了-->
<appender name="WlcLog" class="com.logback.wlcLogLogbackAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--ERROR級(jí)別調(diào)用-->
<root level="ERROR">
<appender-ref ref="ERROR_FILE" />
<appender-ref ref="WlcLog" />
</root>
<root level="TRACE">
<appender-ref ref="TRACE_FILE" />
</root>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
當(dāng)然由于
判斷了異常不為空時(shí),想要進(jìn)去判斷,就需要在log輸出日志時(shí),要注入 Throwable
如下
必須用 log.error("這是一個(gè)日志msg", e);
這樣
ThrowableProxy throwableProxy = (ThrowableProxy) loggingEvent.getThrowableProxy();
throwableProxy 就不等于 null
像 log.error("這是一個(gè)日志msg");
throwableProxy 就等于 null
這樣自定義一個(gè)日志處理處理類 wlcLogLogbackAppender 就生效了
你可以 wlcLogLogbackAppender 在里面你可以拿到日志信息,做一些自己想做的事情。比如我這邊就是在里面發(fā)送郵件,當(dāng)然你可以做任何事
發(fā)郵件的代碼就不分享了,有興趣的可以去看上一篇文章。
作者:IT學(xué)習(xí)道場(chǎng)
歡迎關(guān)注微信公眾號(hào) : IT學(xué)習(xí)道場(chǎng)