【告警通知】Java项目统一异常捕获处理【钉钉告警推送消息】

基础描述

  • 在实际业务中,很多时候都是被动获取系统业务异常,如通过业务部门或者通过客户反馈说某个功能不行时,这样显得系统很被动和呆板
  • 在SpringBoot中有统一异常处理可以来实现,当我们检测到非业务异常时,比如空指针异常、数组越界异常等
  • 我们可以主动知晓异常发生的时间和业务场景,方便系统主动捕获异常,快速定位处理
  • 但都遇到过一样的事情——系统异常导致损失。这似乎成了每个公司都必须要经历的事情
  • 不管是电商行业还是金融行业,凡涉及到交易的业务,其实都会有很大的系统风险。例如,系统或者接口异常导致用户无法完成交易,这对公司来说是交易额的损失。又比如,运营人员操作不当导致被刷单或者薅羊毛,这对公司来说是利润的损失
    在这里插入图片描述

钉钉机器人创建

新建群

  • 创建一个钉钉群,用于接收告警消息
    在这里插入图片描述
    在这里插入图片描述

新建钉钉机器人

  • 点击群设置
    在这里插入图片描述
  • 点击机器人
    在这里插入图片描述
  • 选择自定义
    在这里插入图片描述
  • 进行配置
    在这里插入图片描述
    在这里插入图片描述
  • 保存好密钥和webhook通知地址
  • 收到告警消息
    在这里插入图片描述

统一异常捕获

  • 统一异常处理
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    
    

    @Autowired
    DingMsgService dingMsgService;

    @ExceptionHandler(Exception.class)
    public R handleException(Exception e) {
    
    
        log.error(e.getMessage(), e);
        try {
    
    
            // 后续数据可入库
            dingMsgService.sendDingTalkMsg(JSONObject.toJSONString(e));
        } catch (Exception ee) {
    
    
            log.error("发送异常信息接口异常", ee);
        }
        return R.fail(e.getMessage());
    }
}

发送钉钉消息

  • 配置yaml
# 公共配置
config:
  dingtalk:
    secret: SECe1a978f33f20ec1e91091a91ff52a3d2da0bb1afb48ef69d183ec9de7d35681f
    webhook: https://oapi.dingtalk.com/robot/send?access_token=20347ef4a6b6a8086227f5c36c09d62d452f787674be17cc6caa062d2d76e8ea

发送钉钉消息核心代码

@Slf4j
@Service
public class DingMsgService {
    
    

    @Value("${config.dingtalk.secret}")
    private String dingtalkSecret;

    @Value("${config.dingtalk.webhook}")
    private String dingtalkWebhook;


    public void sendDingTalkMsg(String content) {
    
    

        // 钉钉最大只能发送2000个字符
        if (content.length() >= 1990) {
    
    
            content = content.substring(0, 1990);
        }

        DingTalkSendMsgRequestDTO requestDTO = new DingTalkSendMsgRequestDTO();
        requestDTO.setSecret(dingtalkSecret);
        requestDTO.setWebhook(dingtalkWebhook);
        requestDTO.setContent(content);

        //消息内容
        Map<String, String> contentMap = new HashMap<>();
        contentMap.put("content", requestDTO.getContent());
        //通知人
        Map<String, Object> atMap = new HashMap<>();
        //1.是否通知所有人
        atMap.put("isAtAll", requestDTO.getIsAtAll());
        //2.通知具体人的手机号码列表
        atMap.put("atMobiles", requestDTO.getMobileList());
        Map<String, Object> reqMap = new HashMap<>();
        reqMap.put("msgtype", "text");
        reqMap.put("text", contentMap);
        reqMap.put("at", atMap);
        requestDTO.setContent(JSON.toJSONString(reqMap));

        try {
    
    
            String secret = requestDTO.getSecret();
            //获取系统时间戳
            long timestamp = Instant.now().toEpochMilli();
            //拼接
            String stringToSign = timestamp + "\n" + secret;
            //使用HmacSHA256算法计算签名
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
            byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
            //进行Base64 encode 得到最后的sign,可以拼接进url里
            String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
            //钉钉机器人地址(配置机器人的webhook)
            String dingUrl = requestDTO.getWebhook() + "&timestamp=" + timestamp + "&sign=" + sign;

            String result = HttpUtil.post(dingUrl, requestDTO.getContent());
            log.info("re={}", result);
        } catch (Exception e) {
    
    
            log.error("钉钉推送消息出现异常", e);
        }
    }
}

示例代码

@RestController
public class TestController {
    
    

    @GetMapping(value = "test")
    public R test() {
    
    
        // 异常代码
        System.out.print(1 / 0);
        return R.ok();
    }
}

源码地址

其他

  • 我们平时开发接口时,遇到接口异常,我们希望能第一时间得知
  • 以往的经验我们是通过邮件等方式告知相对于的人员
  • 现在大多数的告警可以发送到相关的app上了
  • 群机器人是钉钉群的高级扩展功能,群机器人可以将第三方服务的信息聚合到群聊中,实现自动化的信息同步
  • 借助钉钉机器人,通过调用官方提供的API,我们可以很方便地将异常告警信息通知到到相应的人员

猜你喜欢

转载自blog.csdn.net/u010800804/article/details/130477842
今日推荐