基础描述
- 在实际业务中,很多时候都是被动获取系统业务异常,如通过业务部门或者通过客户反馈说某个功能不行时,这样显得系统很被动和呆板
- 在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());
}
}
发送钉钉消息
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) {
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<>();
atMap.put("isAtAll", requestDTO.getIsAtAll());
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;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
String dingUrl = requestDTO.getWebhook() + "×tamp=" + 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,我们可以很方便地将异常告警信息通知到到相应的人员