开发过程中,难免会有发生错误或异常的时候,有些是需要及时通知到相关开发人员的。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>
四、记日志报错
参考: