1、引入钉钉的maven 依赖
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
<version>1.0.1</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
2、自定义appender
public class DingTalkAppender extends AppenderBase<LoggingEvent> {
PatternLayoutEncoder encoder;
//多级自定义配置,需Getter和Setter方法
DingTalkLogbackParam dingTalkLogbackParam;
@Override
public void start() {
//可以做一些初始化相关资源的操作,如数据库连接,redis线程池等等
if (this.encoder == null) {
//name : logback.xml 中 appender 标签 配置的name值
addError("No encoder set for the appender named [" + name + "].");
return;
}
super.start();
}
@Override
public void stop() {
//可以做一些释放相关资源的操作,如数据库连接,redis线程池等等
System.out.println("stop方法被调用");
if (!isStarted()) {
return;
}
super.stop();
}
@Override
protected void append(LoggingEvent eventObject) {
/**
* 指定只有 error 级别的日志,才发消息
* 后续可以根据配置指定,此处暂不实现
*/
if (dingTalkLogbackParam == null) {
return;
}
boolean sendMsg = dingTalkLogbackParam.isSendMsg();
if (!sendMsg) {
addInfo("不输出日志===================");
return;
}
Level level = eventObject.getLevel();
if (Level.ERROR.levelInt == level.levelInt) {
String accessToken = dingTalkLogbackParam.getWebHookAccessToken();
if (StringUtils.isEmpty(accessToken)) {
System.out.println("没有匹配的name和token");
addError("No dingTalk accessToken for the appender named [" + name + "].");
return;
}
String message = eventObject.getMessage();
if (StringUtils.isNotEmpty(dingTalkLogbackParam.getMarkMsg())) {
message = dingTalkLogbackParam.getMarkMsg().concat("---").concat(message);
}
// 发钉钉报警消息
DingTalkSenMsgService.sendTextMsg(message,accessToken);
}
}
public PatternLayoutEncoder getEncoder() {
return encoder;
}
public void setEncoder(PatternLayoutEncoder encoder) {
this.encoder = encoder;
}
public DingTalkLogbackParam getDingTalkLogbackParam() {
return dingTalkLogbackParam;
}
public void setDingTalkLogbackParam(DingTalkLogbackParam dingTalkLogbackParam) {
this.dingTalkLogbackParam = dingTalkLogbackParam;
}
}
3、自定义appender的属性参数对象,用于在logback.xml 中 设置自定义的属性
public class DingTalkLogbackParam {
/**
* 是否要发钉钉消息
*/
private boolean sendMsg = false;
/**
* robot token
*/
private String webHookAccessToken;
/**
* 关键词标识,若配置 消息以 【markMsg】 开始,同时匹配钉钉的关键词策略
*/
private String markMsg;
public boolean isSendMsg() {
return sendMsg;
}
public void setSendMsg(boolean sendMsg) {
this.sendMsg = sendMsg;
}
public String getWebHookAccessToken() {
return webHookAccessToken;
}
public void setWebHookAccessToken(String webHookAccessToken) {
this.webHookAccessToken = webHookAccessToken;
}
public String getMarkMsg() {
return markMsg;
}
public void setMarkMsg(String markMsg) {
this.markMsg = markMsg;
}
}
4、发消息工具类
public class DingTalkSenMsgService {
private static final String dingTalkWebHookDomain = "https://oapi.dingtalk.com/robot/send?access_token=";
/**
* 发送json串消息
*/
public static boolean sendTextMsg(String content, String accessToken) {
return sendTextMsg(content, accessToken, null);
}
public static boolean sendTextMsg(String content, String accessToken, String keyWords) {
Assert.notNull(content, "消息内容不能为空");
Assert.notNull(accessToken, "accessToken不能为空");
if (StringUtils.isNotEmpty(keyWords)) {
content = keyWords.concat(content);
}
try {
OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
text.setContent(content);
String tokenURL = dingTalkWebHookDomain.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) {
}
return true;
}
}
5、配置logback.xml
<!-- 通过配置文件的方式引入自定义appender的相关配置信息 -->
<springProperty name="ding.talk.webhook.send.msg" source="ding.talk.webhook.send.msg"/>
<springProperty name="ding.talk.webhook.mark.msg" source="ding.talk.webhook.mark.msg"/>
<springProperty name="ding.talk.webhook.access.token" source="ding.talk.webhook.access.token"/>
<!-- 控制台输出 -->
<appender name="dingTalkAppenderSync"
class="cn.xx.common.logback.DingTalkAppender">
<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>
<!-- 自定义参数 -->
<dingTalkLogbackParam>
<sendMsg>${ding.talk.webhook.send.msg}</sendMsg>
<markMsg>${ding.talk.webhook.mark.msg}</markMsg>
<webHookAccessToken>${ding.talk.webhook.access.token}</webHookAccessToken>
</dingTalkLogbackParam>
</appender>
<!-- 发消息异步输出 -->
<appender name ="dingTalkAppenderAsync" class= "ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold >0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>512</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref ="dingTalkAppenderSync"/>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="dingTalkAppenderAsync"/>
</root>