sentry告警之webhook
2021-08-31 本文已影响0人
天草二十六_简村人
一、背景
sentry告警支持自定义插件,但是最新的版本(21.8.0)默认只集成了webhook,没有了企业微信,更无法支持钉钉。所以我们要实现其他的告警方式,比如短信、电话等其他方式,可以接收它的回调字段以扩展多种消息通知方式。
二、sentry的设置
1、增加告警渠道
step-1.png step-2.png step3.png2、新增告警规则
step-1.png step-2.png到这里,sentry的设置就已完成。
接下来就是要实现webhook,接收并解析回调信息,然后调用企业微信、SMS等渠道发送给对应的用户。
三、webhoook实现
1、回调字段
event明细.png可以自己写一个post的urimapping,将其完整打印,详见下面的java示例代码。
第一层.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()