springboot中logback自动发送error日志告警到钉钉

1、自定义appender,先在logback.xml中配置

  

2、配置Appender引用,这步不能少,少了Appender不启作用


        
        
        
    

    
        
        
        
    

 

3、extends UnsynchronizedAppenderBase 用于异步处理,不阻塞主线程;例如自定义发送日志到消息队列。

需要在钉钉群创建机器人,并在电脑客户端获取access_token

@Slf4j
public class SendErrorMsgAppender extends UnsynchronizedAppenderBase {

    private static final String url = "https://oapi.dingtalk.com/robot/send?access_token=%s";

    private HttpHeaders headers;

    public SendErrorMsgAppender() {
        headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
    }

    @Override
    public void append(ILoggingEvent event) {
        if (event.getLevel() == Level.ERROR) {
            SysProperties sysProperties = getApplicationContext().getBean("sysProperties", SysProperties.class);
            //没有启用
            if (!sysProperties.getWaringDingdingEnable()) {
                return;
            }
            IThrowableProxy iThrowableProxy = event.getThrowableProxy();
            StringBuilder sb = new StringBuilder();
            if (iThrowableProxy != null && iThrowableProxy instanceof ThrowableProxy) {
                ThrowableProxy throwableProxy = (ThrowableProxy) iThrowableProxy;
                Throwable throwable = throwableProxy.getThrowable();
                String throwableMsg = throwable.getMessage();
                StackTraceElementProxy[] stackTraceElementProxy = iThrowableProxy.getStackTraceElementProxyArray();
                //获取服务器Ip,告知哪台服务器抛异常
                String ip = Context.getContext().getIp();
                if (null != ip) {
                    sb.append("服务器:").append(ip).append("\n");
                }
                sb.append(event.getMessage()).append("\n");
                if (StringUtils.isNotEmpty(throwableMsg)) {
                    sb.append(throwableMsg).append("\n");
                }
                int i = 0;
                for (StackTraceElementProxy proxy : stackTraceElementProxy) {
                    //只打印40行的堆栈
                    if (i < 40) {
                        sb.append(proxy.getSTEAsString()).append("\n");
                    } else {
                        break;
                    }
                    i++;
                }
            } else {
                sb.append(event.getMessage());
            }
            String msg = sb.toString();
            if (StringUtils.isNotEmpty(msg)) {
                sendMsgToDingDing(msg);
            }
        }
    }


    /**
     * @param msg
     * @return
     */
    private Map sendMsgToDingDing(String msg) {
        RestTemplate restTemplate = getApplicationContext().getBean("restTemplate", RestTemplate.class);
        SysProperties sysProperties = getApplicationContext().getBean("sysProperties", SysProperties.class);
        ObjectMapper objectMapper = getApplicationContext().getBean("jacksonObjectMapper", ObjectMapper.class);
        Text text = new Text();
        text.setContent(msg);
        DdMsgBody msgBody = DdMsgBody.builder().msgtype("text").text(text).build();
        String json = null;
        try {
            json = objectMapper.writeValueAsString(msgBody);
        } catch (JsonProcessingException e) {
            //不记录日志,有可能死循环
            //log.error("error", e);
        }
        if (null == json) {
            return null;
        }
        HttpEntity formEntity = new HttpEntity<>(json, headers);
        String formatUrl = String.format(url, sysProperties.getWaringDingdingToken());
        Map result = restTemplate.postForObject(formatUrl, formEntity, Map.class);
        return result;
    }

    private ApplicationContext getApplicationContext() {
        return ApplicationContextUtils.getApplicationContext();
    }

    @Builder
    @Data
    private static class DdMsgBody {
        private String msgtype;
        private Text text;
    }

    @Data
    private class Text {
        private String content;
    }

}

 

你可能感兴趣的:(springboot中logback自动发送error日志告警到钉钉)