1、背景:
自定义appender, 针对日志级别,指定日志级别的输出,同时发送到钉钉,实现日志报警监控
钉钉自定义机器人开发文档:文档钉钉开放平台
钉钉sdk下载:文档钉钉开放平台
2、实现方式:
快速demo可参看: 开发的 dingtalk-log-springboot-start 包
GitHub - cutiyu/dinglog-spring-boot-started: 基于钉钉的webhook,实现钉钉消息日志报警,及封装了钉钉发消息接口
以下两种方式,实现任意一个即可
1)、 自定义Appender 继承UnsynchronizedAppenderBase<ILoggingEvent>
extends UnsynchronizedAppenderBase<ILoggingEvent>
具体实现:
@Getter
@Setter
public class DingTalkAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
Layout<ILoggingEvent> layout;
//自定义配置
String printString;
@Override
public void start(){
/**
* 这里可以做些初始化判断 比如layout不能为null
*/
if(layout == null) {
addWarn("Layout was not defined");
}
/**
* 或者写入数据库 或者redis时 初始化连接等等
*/
super.start();
}
@Override
public void stop()
{
/**
* 释放相关资源,如数据库连接,redis线程池等等
*/
System.out.println("logback-stop方法被调用");
if(!isStarted()) {
return;
}
super.stop();
}
@Override
public void append(ILoggingEvent event) {
if (event == null || !isStarted()){
return;
}
/**
* 自定义日志输出的逻辑
* 比如 操作数据库 redis kafka
* 当然,我的本质目的是发钉钉消息
*/
System.out.print("获取输出值"+event.getFormattedMessage());
System.out.println("格式化输出日志:"+printString + ":" + layout.doLayout(event));
System.out.println("============================================== MyLogbackAppender要发消息了");
//发钉钉消息: 具体处理逻辑,参考钉钉的文档
//后续计划会开发一个 dingtalk-log-springboot-start 包
//已经写了,可参看:https://github.com/cutiyu/dinglog-spring-boot-started
try {
OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
text.setContent("这是一个测试");
//https://oapi.dingtalk.com/robot/send?access_token=
String accessToken = "{填入自己钉钉群自定义机器人的 webhook token}";
String tokenURL = "https://oapi.dingtalk.com/robot/send?access_token=".concat(accessToken);
DingTalkClient client = new DefaultDingTalkClient(tokenURL);
OapiRobotSendRequest request = new OapiRobotSendRequest();
request.setMsgtype("text");
request.setText(text);
//OapiRobotSendResponse response = client.execute(request);
} catch (Exception e) {
}
}
}
2)、自定义Appender 继承AppenderBase<LoggingEvent>
extends AppenderBase<LoggingEvent>
@Getter
@Setter
public class DingTalkAppender2 extends AppenderBase<LoggingEvent> {
PatternLayoutEncoder encoder;
@Override
public void start() {
if (this.encoder == null) {
//name : logback.xml 中 appender 标签 配置的name值
addError("No encoder set for the appender named [" + name + "].");
return;
}
try {
encoder.init(System.out);
} catch (IOException e) {
}
super.start();
}
@Override
public void stop() {
//释放相关资源,如数据库连接,redis线程池等等
System.out.println("stop方法被调用");
if (!isStarted()) {
return;
}
super.stop();
}
@Override
protected void append(LoggingEvent eventObject) {
Level level = eventObject.getLevel();
/**
* 指定只有 error 级别的日志,才发消息
* 后续可以根据配置指定,此处暂不实现
*/
if (level.ERROR.levelInt == level.levelInt) {
System.out.println("DingTalkAppender2============================================== 要发钉钉消息了");
/**
* 发钉钉消息的逻辑,参看钉钉文档,
* 后续计划会开发一个 dingtalk-log-springboot-start 包
*/
try {
OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
text.setContent("告警任务:验证日志输出同时发钉钉消息");
//https://oapi.dingtalk.com/robot/send?access_token=
String accessToken = "{填入自己钉钉群自定义机器人的 webhook token}";
String tokenURL = "https://oapi.dingtalk.com/robot/send?access_token=".concat(accessToken);
DingTalkClient client = new DefaultDingTalkClient(tokenURL);
OapiRobotSendRequest request = new OapiRobotSendRequest();
request.setMsgtype("text");
request.setText(text);
OapiRobotSendResponse response = client.execute(request);
System.out.println(JSONObject.toJSONString(response));
} catch (Exception e) {
}
}
}
}
3、自定义的Appender配置到logback.xml中
<appender name="DingTalkAppender2"
class="com.xx.xx.xxx.DingTalkAppender2">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!-- 日志收集最低日志级别 -->
<level>ERROR</level>
</filter>
<encoder>
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!-- 自定义参数 -->
<!--<printString>DingTalkAppender2的logback日志输出</printString>-->
</appender>
<!-- 控制台输出 -->
<appender name="DingTalkAppender"
class="com.xx.xx.xx.xx.xx.DingTalkAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!-- 日志收集最低日志级别 -->
<level>INFO</level>
</filter>
<layout
class="ch.qos.logback.classic.PatternLayout">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</layout>
<!-- 自定义参数 -->
<printString>DingTalkAppender的logback日志输出</printString>
</appender>
<!-- 把自定义的appender 配置到root 中 -->
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="DingTalkAppender"/>
<appender-ref ref="DingTalkAppender2"/>
</root>
4、启动项目正常输出日志,就能看到自定义日志的逻辑处理了。