Spring boot

sentry告警之webhook

2021-08-31  本文已影响0人  天草二十六_简村人

一、背景

sentry告警支持自定义插件,但是最新的版本(21.8.0)默认只集成了webhook,没有了企业微信,更无法支持钉钉。所以我们要实现其他的告警方式,比如短信、电话等其他方式,可以接收它的回调字段以扩展多种消息通知方式。

二、sentry的设置

1、增加告警渠道

step-1.png step-2.png step3.png

2、新增告警规则

step-1.png step-2.png

到这里,sentry的设置就已完成。
接下来就是要实现webhook,接收并解析回调信息,然后调用企业微信、SMS等渠道发送给对应的用户。

三、webhoook实现

1、回调字段

可以自己写一个post的urimapping,将其完整打印,详见下面的java示例代码。


第一层.png
event明细.png
    @PostMapping("/api/msg/callback")
    @ResponseBody
    public String notify(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String requestResultJson = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
        if (log.isInfoEnabled()) {
            log.info("回调报文内容是:{}", requestResultJson);
        }
        Map<String, Object> resultMap = JSON.parseObject(requestResultJson, HashMap.class);

       // 自定义的扩展字段,也就是写在?后面的字段
       String group = request.getParameter("group");
    }

2、拼接消息内容

2.1、接口

public interface SentryWebhookService {
    String APPLICATION_ID = "operation";

    String DEFAULT_GROUP = "trade";

    String MSG_SUBJECT = "sentry报警";

    String MSG_TEMPLATE = "**${projectName}** --- ${environment}环境下出现<font color=\"warning\">告警</font>,需要及时跟进!! \n" +
            "> 版 本  : **${release}** \n" +
            "> \n" +
            "> 时 间  : <font color=\"info\">${timestamp}</font> \n" +
            "> \n" +
            "> URL   : **${culprit}** \n" +
            "> \n" +
            "> Log类  : **${logger}** \n" +
            "> \n" +
            "> 详 情 :[${message}](${url}) \n " +
            "> \n" +
            "> [如无法点击,请复制网址: `${url}]`\n";

    /**
     * 解析sentry回调信息
     *
     * @param sentryAlertsRequest
     * @return
     */
    Map<String, String> parseNotify(String sentryAlertsRequest);
}

2.2、实现类

@Slf4j
@Service
public class SentryWebhookServiceImpl implements SentryWebhookService {

    @Override
    public Map<String, String> parseNotify(String sentryAlertsRequest) {
        JSONObject jsonObject = JSON.parseObject(sentryAlertsRequest);

        Map<String, String> paramMap = Maps.newHashMap();
        paramMap.put("projectName", jsonObject.getString("project_name"));
        paramMap.put("level", jsonObject.getString("level"));
        paramMap.put("culprit", jsonObject.getString("culprit"));
        paramMap.put("message", jsonObject.getString("message"));
        paramMap.put("logger", jsonObject.getString("logger"));
        paramMap.put("url", jsonObject.getString("url"));

        // 解析event中的时间戳,环境以及版本号
        JSONObject eventObject = jsonObject.getJSONObject("event");

        BigDecimal timestamp = new BigDecimal(eventObject.getString("timestamp"));
        paramMap.put("timestamp", String.valueOf(DateUtils.ofEpochSecond(timestamp.longValue())));

        paramMap.put("environment", eventObject.getString("environment"));
        paramMap.put("release", eventObject.getString("release"));

        return paramMap;
    }

}

2.3、工具类

@Slf4j
public class MessageTemplateUtil {

    public static String parseTemplate(String content, Map<String, String> paramMap) {
        try {
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                String regex = "\\$\\{" + entry.getKey() + "\\}";

                Pattern pattern = Pattern.compile(regex);

                Matcher matcher = pattern.matcher(content);

                content = matcher.replaceAll(entry.getValue());
            }
        } catch (Exception e) {
            log.error("解析消息模板出现异常, content={}, paramMap={}", content, JSON.toJSON(paramMap), e);
        }
        return content;
    }
}

2.4、spring mvc

@Slf4j
@Api(value = "sentry回调", tags = "sentry回调")
@RestController
public class SentryCallbackFacade {
    @Autowired
    private MessageService messageService;

    @Autowired
    private SentryWebhookService sentryWebhookService;

    @PostMapping(value = "/api/sentry/notify")
    public ResponseEntity<?> sentryNotify(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        // 回调内容,调试阶段,你通过log.info()打印输出
        String sentryAlertsRequestJson = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
        log.debug(sentryAlertsRequestJson);
        // 从回调字段里抽取消息内容需要的字段 
        Map<String, String> paramMap = sentryWebhookService.parseNotify(sentryAlertsRequestJson);
        // 接收消息的群组
        String group = request.getParameter("group");
        // 拼接消息内容
        final String payload = MessageTemplateUtil.parseTemplate(SentryWebhookService.MSG_TEMPLATE, paramMap);
        // 发送消息
        messageService.deliverMessage();

        return ResponseEntity.noContent().build();
    }

}

3、调用消息渠道

可以是短信、企业微信等渠道,具体不在本文的介绍中。
对应上面的messageService.deliverMessage()

上一篇下一篇

猜你喜欢

热点阅读