企业微信机器人告诉

描绘

出产环境对反常监控实时性要求比较高,通常状况咱们都会运用邮件报警,非常重要的会运用短信报警。邮件咱们简略忽略,并且邮箱空间有限需求定期整理,短信又要收费,所以咱们要采用一种既要免费又要实时性高的方法,那就是咱们平常作业所用的交流东西(企微,钉钉)

意图

ERROR等级日志实时报警

自定义业务预正告诉

对系统无侵入规划

能够快速定位问题

最重要能够实时群发告诉

邮件告诉

机器人实时通知

可以看到邮件告诉非常多,并且及时性也不行

计划

已然要无侵入规划,就不能到处埋点,终究挑选自定义Appender的方法处理

因为公司内部作业交流东西是企业微信,所以就凭借企业微信机器人发送实时告诉音讯,根据恳求链路ID结合ELK东西就可以从音讯告诉直接跳转到ELK,检查完整的链路日志从而快速定位问题

废话不多说直接上代码。。。

ErrorWarnAppender

public class ErrorWarnAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
    @Setter
    private String packageNames;
    @Override
    protected void append(ILoggingEvent event) {
        if (null == event || "DEV".equalsIgnoreCase(ApplicationHelper.getEnv()) || StrUtil.isEmpty(MDC.get(ScmConstant.REQUEST_ID))) {
            return;
        }
        boolean success = Arrays.stream(packageNames.split(",")).anyMatch(event.getLoggerName()::startsWith);
        if (!success) {
            return;
        }
        if (null == event.getThrowableProxy()) {
            RobotUtil.sendWarn(event.getFormattedMessage());
        } else {
            RobotUtil.sendWarn(event.getFormattedMessage(), event.getThrowableProxy().getClassName() + ":" + event.getThrowableProxy().getMessage());
        }
    }
}

RobotUtil

public class RobotUtil {
    /**
     * 正告地址
     */
    private static final String WARN_URL = "XXX";
    /**
     * 告诉地址
     */
    private static final String NOTICE_URL = "XXX";
    /**
     * 测验环境ELK地址
     */
    private static final String ELK_URL = "XXX";
    /**
     * 出产环境ELK地址
     */
    private static final String PRD_ELK_URL = "XXX";
    /**
     * 发送企业微信机器人告诉音讯
     *
     * @param message
     */
    public static void sendNotice(StringBuilder message) {
        try {
            // 发送告诉音讯
            if (isPro()) {
                HttpUtil.post(NOTICE_URL, RobotUtil.getMessage(message));
            } else {
                message.insert(0, "env:" + ApplicationHelper.getEnv() + "\n");
                HttpUtil.post(WARN_URL, RobotUtil.getMessage(message));
            }
        } catch (Exception ignored) {
        }
    }
    /**
     * 发送企业微信机器人正告音讯
     *
     * @param message
     */
    public static void sendWarn(String message) {
        sendWarn(message, null);
    }
    /**
     * 发送企业微信机器人正告音讯
     *
     * @param message
     * @param exception
     */
    public static void sendWarn(String message, String exception) {
        if (!ApplicationHelper.getSendWarnEnable()) {
            return;
        }
        try {
            String requestId = MDC.get(ScmConstant.REQUEST_ID);
            StringBuilder text = new StringBuilder();
            text.append("env:").append(isPro() ? "<font color=\"red\">**出产环境**</font>" : ApplicationHelper.getEnv()).append("\n");
            text.append("applicationName:").append(ApplicationHelper.getApplicationName()).append("\n");
            if (StrUtil.isNotEmpty(requestId)) {
                text.append("requestId:").append("[").append(requestId).append("](").append(String.format(isPro() ? PRD_ELK_URL : ELK_URL, requestId)).append(")").append("\n");
            }
            text.append("message:").append(StrUtil.subPre(message, 1000)).append("\n");
            if (StrUtil.isNotEmpty(exception)) {
                text.append("exception:").append(StrUtil.subPre(exception, 1000)).append("\n");
            }
            // 发送正告音讯
            HttpUtil.post(WARN_URL, RobotUtil.getMessage(text));
        } catch (Exception ignored) {
        }
    }
    /**
     * 音讯内容
     *
     * @param message
     * @return
     */
    private static String getMessage(Object message) {
        Map<String, Object> textMap = new HashMap<>();
        textMap.put("msgtype", "markdown");
        Map<String, Object> contentMap = new HashMap<>();
        contentMap.put("content", message);
        textMap.put("markdown", contentMap);
        return JSONUtil.toJsonStr(textMap);
    }
    /**
     * 是否出产环境
     *
     * @return
     */
    private static boolean isPro() {
        return "PRO".equalsIgnoreCase(ApplicationHelper.getEnv());
    }
}

logback装备

1、添加appender 装备
<appender name="ERROR_WARN" class="org.slf4j.ErrorWarnAppender">
    <packageNames>org.xx,com.xx,com.yy</packageNames>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>ERROR</level>
    </filter>
</appender>
2、各个环境增加appender
<springProfile name="test">
    <root level="INFO">
        <appender-ref ref="INFO_FILE"/>
        <appender-ref ref="ERROR_FILE"/>
        <appender-ref ref="ERROR_WARN"/>
    </root>
</springProfile>
<springProfile name="prd">
    <root level="INFO">
        <appender-ref ref="INFO_FILE"/>
        <appender-ref ref="ERROR_FILE"/>
        <appender-ref ref="ERROR_WARN"/>
    </root>
</springProfile>

作用展现

机器人实时通知
机器人实时通知

可以看到音讯能够区分环境,使用名称,链路ID,错误信息(出产环境红色夺目提醒)

注意事项

1、音讯每分钟最多发送20条\color{red}音讯每分钟最多发送20条

发送企业微信音讯是https恳求接口,每分钟约束最多20条音讯,所以反常报警只发送error等级的告诉

同时还可以凭借于kafka异步音讯,发送邮件,短信 等等音讯告诉

2、音讯体长度最大支撑4000字符\color{red}音讯体长度最大支撑4000字符

咱们会把message和exception 截取前1000个字符

3、需求简略了解markdown语法\color{red}需求简略了解markdown语法

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。