钉钉机器人监控项目异常_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(钉钉机器人)消费消息(报警)。

posted @ 2023-08-18 13:18  Ashe|||^_^  阅读(90)  评论(1编辑  收藏  举报