開發過程中,難免會有發生錯誤或異常的時候,有些是需要及時通知到相關開發人員的。logback可以通過簡單的配置達到郵件告警的目的。
一、錯誤告警
如下配置,所有Error級別的log發送郵件告警給receiver(多個receiver以逗號分隔)
<?xml version="1.0" encoding="UTF-8"?> <configuration> <springProperty scope="context" name="receiver" source="log.email.receiver" defaultValue="xxxxxx@qq.com"/> <springProperty scope="context" name="env" source="spring.profiles.active" defaultValue="dev"/> <property name="smtpHost" value="localhost" /> <property name="smtpPort" value="25" /> <property name="username" value="username" /> <property name="password" value="password" /> <property name="from" value="send@126.com" /> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%level][%thread]:%logger{50} [%method:%line] %msg%n</pattern> </encoder> </appender> <appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender"> <cyclicBufferTracker class="ch.qos.logback.core.spi.CyclicBufferTracker"> <bufferSize>1</bufferSize> </cyclicBufferTracker> <smtpHost>${smtpHost}</smtpHost> <smtpPort>${smtpPort}</smtpPort> <username>${username}</username> <password>${password}</password> <from>${from}</from> <to>${receiver}</to> <subject>【test-email Error】【${env}環境】: %logger{20} - %m </subject> <layout class="ch.qos.logback.classic.html.HTMLLayout"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS}%level%thread%logger{35}%message</pattern> </layout> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <springProfile name="dev,test"> <root> <level value="info"/> <appender-ref ref="STDOUT"/> <appender-ref ref="EMAIL"/> </root> </springProfile> <springProfile name="uat,pro"> <root> <level value="info"/> <appender-ref ref="EMAIL"/> </root> </springProfile> </configuration>
Error級別日志:
log.error("an unexpected error!");
收到告警郵件:
記入ex,可以看到詳細的堆棧信息。
a、springProperty 從spring讀取配置
<springProperty scope="context" name="receiver" source="log.email.receiver" defaultValue="xxxxxx@qq.com"/>
scope:context 參考(官網)
name:定義的變量名
source:需要spring配置的節點名稱。(eg:log.email.receiver=xxx@126.com,yyy@qq.com)
defaultValue:默認值
二、自定義告警
上面是對所有Error級別日志的告警,有時候需要對正常業務的郵件通知,此時可以用Mark來發郵件。
<?xml version="1.0" encoding="UTF-8"?> <configuration> <springProperty scope="context" name="receiver" source="log.email.receiver" defaultValue="xxxxxx@qq.com"/> <springProperty scope="context" name="env" source="spring.profiles.active" defaultValue="dev"/> <property name="smtpHost" value="localhost" /> <property name="smtpPort" value="25" /> <property name="username" value="username" /> <property name="password" value="password" /> <property name="from" value="send@126.com" /> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%level][%thread]:%logger{50} [%method:%line] %msg%n</pattern> </encoder> </appender> <appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender"> <cyclicBufferTracker class="ch.qos.logback.core.spi.CyclicBufferTracker"> <bufferSize>1</bufferSize> </cyclicBufferTracker> <smtpHost>${smtpHost}</smtpHost> <smtpPort>${smtpPort}</smtpPort> <username>${username}</username> <password>${password}</password> <from>${from}</from> <to>${receiver}</to> <subject>【開發人員關注】【${env}環境】</subject> <layout class="ch.qos.logback.classic.html.HTMLLayout"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS}%level%thread%logger{35}%message</pattern> </layout> <!-- 基於標記的發送郵件 這里我們加入一個標記DEVELOP,發送日志時只需加入此標記即可,如有多個標記加入多個<maker></maker>標簽即可 --> <evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator"> <marker>DEVELOP</marker> </evaluator> </appender> <springProfile name="dev,test"> <root> <level value="info"/> <appender-ref ref="STDOUT"/> <appender-ref ref="EMAIL"/> </root> </springProfile> <springProfile name="uat,pro"> <root> <level value="info"/> <appender-ref ref="EMAIL"/> </root> </springProfile> </configuration>
Mark郵件示例:
log.info(MarkerFactory.getMarker("DEVELOP"), "notify developers!");
郵件:
三、自定義郵件格式
郵件自定義格式。實現自定義的 HTMLLayout:

public class MyHtmlLayout extends HTMLLayout { IThrowableRenderer<ILoggingEvent> throwableRenderer; private String tag; public MyHtmlLayout() { super(); this.throwableRenderer = new DefaultThrowableRenderer(); } @Override public String doLayout(ILoggingEvent event) { StringBuilder buf = new StringBuilder(); this.startNewTableIfLimitReached(buf); boolean odd = true; if((this.counter++ & 1L) == 0L) { odd = false; } String level = event.getLevel().toString().toLowerCase(); buf.append(CoreConstants.LINE_SEPARATOR); buf.append("<tr class=\""); buf.append(level); if(odd) { buf.append(" odd\">"); } else { buf.append(" even\">"); } buf.append(CoreConstants.LINE_SEPARATOR); for(Converter c = this.head; c != null; c = c.getNext()) { this.appendEventToBuffer(buf, c, event); } buf.append("</tr>"); buf.append(CoreConstants.LINE_SEPARATOR); if(event.getThrowableProxy() != null) { throwableRenderer.render(buf, event); } return buf.toString(); } private void appendEventToBuffer(StringBuilder buf, Converter<ILoggingEvent> c, ILoggingEvent event) { buf.append("<td class=\""); buf.append(this.computeConverterName(c)); buf.append("\">"); buf.append(Transform.escapeTags(c.convert(event)) + ",my tag:" + tag); buf.append("</td>"); buf.append(CoreConstants.LINE_SEPARATOR); } public String getTag() { return tag; } public void setTag(String tag) { this.tag = tag; } }
將logback-spring.xml配置改為(配置的tag):
<layout class="com.logback.demo.eval.MyHtmlLayout"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS}%level%thread%logger{35}%message</pattern> <tag>this is my layout tag</tag> </layout>
四、記日志報錯
參考: