springboot打印error报错信息到钉钉群

作者: ʘᴗʘ发布时间:2021-12-14 14:53 浏览量:131 点赞:116 售价:0

前言

springboot jar包部署到服务器后,我们经常需要关注日志是否有报错等信息。但是整天盯着服务器上的日志确实太累了,本文介绍一种可以把springboot日志信息直接同步到钉钉群的方法,供大家参考。

原理介绍

springboot能够将日志直接打印到钉钉群的“自定义机器人”,主要基于下面几点:

  • springboot自带的logback日志框架,支持自定义日志输出形式。
  • 钉钉群提供了可以推送消息的webhook机器人。

原理:配置springboot的日志输出形式,新增一种自定义的输出形式,与传统的打印到控制台、日志文件中等形式不同,新增的形式直接调用钉钉API,将消息推送给钉钉群的自定义机器人。从而实现springboot报错信息打印到钉钉的目的。

效果演示

springboot打印error报错信息到钉钉群

代码演示

一、新建钉钉群的webhook机器人

首先,你得有一个钉钉群,然后在钉钉群点击设置,新增自定义机器人:

springboot打印error报错信息到钉钉群

springboot打印error报错信息到钉钉群

springboot打印error报错信息到钉钉群

springboot打印error报错信息到钉钉群

关于加密方法的配置,请配置“加签”的形式,如下图所示:

springboot打印error报错信息到钉钉群

二、配置自定义输出形式

在springboot项目中,新建一个自定义日志输出文件:DingDingAppender,代码如下:

package com.coderbbb.blogv2.config.log;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.ConsoleAppender;
import com.coderbbb.blogv2.BlogV2Application;
import com.coderbbb.blogv2.service.DingService;

/**
 * Created by coderbbb on 2019-08-26.
 */
public class DingDingAppender extends ConsoleAppender<LoggingEvent> {

    @Override
    protected void append(LoggingEvent eventObject) {
        if (eventObject.getLevel() == Level.ERROR) {
            byte[] byteArray = this.encoder.encode(eventObject);
            String errorMsg = new String(byteArray);

            DingService dingService = BlogV2Application.applicationContext.getBean(DingService.class);
            try {
                dingService.sendErr(errorMsg);
            } catch (Exception ignored) {

            }
        }
    }
}

在springboot的logback日志输出配置文件中,增加对应的日志输出形式:

<appender name="Ding" class="com.coderbbb.blogv2.config.log.DingDingAppender">
    <encoder>
    <pattern>${PATTERN}</pattern>
    </encoder>
</appender>

在logback配置文件中,root节点添加自定义的输出形式:

<root level="info">
    <!--打印日志到文件-->
    <appender-ref ref="coderbbb_FILE"/>
    <!--打印日志到钉钉群-->
    <appender-ref ref="Ding"/>
</root>

完整的logback配置文件代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 文件输出格式 -->
    <property name="PATTERN" value="%d{yyyy-MM-dd HH:mm:ss} %level [%thread] - %class{36}.%M %L - %msg%n"/>

    <!--    <property name="PATTERN" value="%d{HH:mm:ss.SSS} %contextName [%thread] %highlight(%-5level) %logger{36} - %msg%n" />-->
    <!--    <property name="PATTERN" value="%boldGreen(%date{yyyy-MM-dd HH:mm:ss}) %contextName | %highlight(%-5level) | %thread | %logger | %msg%n" />-->

    <!-- test文件路径 -->
    <property name="FILE_PATH" value="logs"/>

    <!-- 每天产生一个文件 -->
    <appender name="coderbbb_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 文件路径 -->
        <file>${FILE_PATH}/coderbbb.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 文件名称 -->
            <fileNamePattern>${FILE_PATH}/coderbbb.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 文件最大保存历史数量 -->
            <MaxHistory>30</MaxHistory>
            <maxFileSize>50MB</maxFileSize>
        </rollingPolicy>

        <encoder>
            <pattern>${PATTERN}</pattern>
        </encoder>
    </appender>

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${PATTERN}</pattern>
        </encoder>
    </appender>

    <appender name="Ding" class="com.coderbbb.blogv2.config.log.DingDingAppender">
        <encoder>
            <pattern>${PATTERN}</pattern>
        </encoder>
    </appender>


    <logger name="org.springframework" level="info"/>
    <logger name="druid.sql" level="error"/>
    <logger name="org.apache" level="error"/>
    <logger name="org.ansj" level="off" />
    <logger name="org.xbill" level="off" />

    <root level="info">
<!--        打印日志到文件-->
        <appender-ref ref="coderbbb_FILE"/>
<!--        打印日志到钉钉群-->
        <appender-ref ref="Ding"/>
    </root>

</configuration>

三、开发钉钉群webhook机器人接口API

钉钉webhook机器人签名算法:

package com.coderbbb.blogv2.utils;

import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.codec.digest.HmacUtils;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class DingUtil {

    public static String sign(long timestamp,String secret) {
        String stringToSign = timestamp + "\n" + secret;
        byte[] hmac = new HmacUtils(HmacAlgorithms.HMAC_SHA_256, secret).hmac(stringToSign);
        return URLEncoder.encode(Base64.getEncoder().encodeToString(hmac), StandardCharsets.UTF_8);
    }

}

封装好的java推送消息导钉钉群webhook机器人代码:

package com.coderbbb.blogv2.service;

import com.coderbbb.blogv2.config.properties.DingDingPropertiesConfig;
import com.coderbbb.blogv2.database.dto.ding.DingBaseDTO;
import com.coderbbb.blogv2.database.dto.ding.DingTextMsg;
import com.coderbbb.blogv2.utils.DingUtil;
import com.coderbbb.blogv2.utils.ObjectMapperUtil;
import com.coderbbb.blogv2.utils.OkhttpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class DingService {

    @Autowired
    private DingDingPropertiesConfig dingDingPropertiesConfig;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    public void sendErr(String message) throws Exception {
        DingBaseDTO dingBaseDTO = new DingBaseDTO();
        dingBaseDTO.setMsgtype("text");

        DingTextMsg dingTextMsg = new DingTextMsg();
        dingTextMsg.setContent(message);
        dingBaseDTO.setText(dingTextMsg);

        String json = ObjectMapperUtil.get().writeValueAsString(dingBaseDTO);
        long timestamp = System.currentTimeMillis();
        String url = dingDingPropertiesConfig.getUrl() + "&timestamp=" + timestamp + "&sign=" + DingUtil.sign(timestamp, dingDingPropertiesConfig.getSign());
        OkhttpUtil.postRaw(url, "application/json;charset=utf-8", json, null);
    }
}

版权声明:《springboot打印error报错信息到钉钉群》为CoderBBB作者「ʘᴗʘ」的原创文章,转载请附上原文出处链接及本声明。

原文链接:https://www.coderbbb.com/articles/54

其它推荐: