钉钉机器人监控项目异常_JavaWeb实现
在prod环境,项目所触发的运行时异常,developer往往无法第一时间得知讯息(在没有项目监控的前提下),为了解决这一问题,可以利用钉钉机器人监控项目异常,实时通知/警报给developer。
1> 自定义紧急异常EmergencyException
2> 在重要业务中产生的异常转换为此异常
3> 在全局异常捕获,针对此异常做特殊处理(发送消息至钉钉群)
在pom.xml引入依赖
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
<version>2.0.0</version>
<!-- 建议排除掉这个日志库,它和Spring的spring-jcl(Spring Commons Logging Bridge)存在冲突 -->
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
自定义异常
/**
* For DingTalk warning
*/
public class EmergencyException extends RuntimeException{
/**
* developer phone number
*/
@Getter
private final String developer;
/**
* title
*/
@Getter
private final String title;
public EmergencyException(String developer, String title){
super();
this.developer = developer;
this.title = title;
}
public EmergencyException(String msg, String developer, String title){
super(msg);
this.developer = developer;
this.title = title;
}
public EmergencyException(String msg, Throwable cause, String developer, String title){
super(msg, cause);
this.developer = developer;
this.title = title;
}
public EmergencyException(Throwable cause, String developer, String title){
super(cause);
this.developer = developer;
this.title = title;
}
}
业务程序中使用
public void dingTalk() {
try {
int a = 1;
int b = 0;
int c = a / b;
log.info("c = {}", c);
} catch (Exception e) {
throw new EmergencyException(e, "152xxxx1282", "xx业务xx功能发生异常");
}
}
异常警报器
@Component
@Slf4j
public class ExceptionAlarm {
private ExceptionAlarm() {
}
/**
* 通知开发人员
*/
public static void noticeDeveloper(String message, String developer, String title) {
try {
// 1-初始化API调用Client 此构造器入参需要更换为你自己的钉钉机器人webhook
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/robot/send?access_token=xxxx");
// 2-初始化请求参数
OapiRobotSendRequest req = new OapiRobotSendRequest();
// 2-1 设置消息类型
req.setMsgtype("text");
// 2-2 设置消息@人
OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
at.setAtMobiles(List.of(developer));
req.setAt(at);
// 2-3 设置消息内容(必须匹配关键词),工作中这里就对应error日志
OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
text.setContent(title + System.lineSeparator() + message);
req.setText(text);
// 3 消息发送
OapiRobotSendResponse rsp = client.execute(req, "");
log.info("钉钉消息发送成功:{}", rsp.getParams().get("text"));
} catch (ApiException e) {
log.error("钉钉消息发送失败:{}", e.getMessage());
}
}
}
DefaultDingTalkClient构造器中的入参来源
全局异常捕获
@ExceptionHandler(value = EmergencyException.class)
public ResponseEntity<String> catchException(EmergencyException e) {
// 记录日志
log.error(e.getTitle(), e);
// 通知运维
// 通知开发
ExceptionAlarm.noticeDeveloper(e.getMessage(), e.getDeveloper(), e.getTitle());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("系统异常,已通知开发人员");
}
演示效果
此设计符合了观察者模式的设计,EmergencyException充当主题(Subject),钉钉机器人充当观察者(Observer),观察到主题(EmergencyException)时触发通知行为(报警)。
从某种角度来看,又类似于MQ,钉钉机器人在监听队列,producer(程序)生产消息(异常),consumer(钉钉机器人)消费消息(报警)。