天天看点

springboot自定义logbackAppender

1、背景:

自定义appender, 针对日志级别,指定日志级别的输出,同时发送到钉钉,实现日志报警监控

钉钉自定义机器人开发文档:https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq

钉钉sdk下载:https://ding-doc.dingtalk.com/doc#/faquestions/vzbp02

2、实现方式:

以下两种方式,实现任意一个即可

1)、 自定义Appender 继承UnsynchronizedAppenderBase<ILoggingEvent>

extends UnsynchronizedAppenderBase<ILoggingEvent>
           

具体实现:

@Getter
@Setter
public class DingTalkAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {

    Layout<ILoggingEvent> layout;

    //自定义配置
    String printString;

    @Override
    public void start(){
        /**
         * 这里可以做些初始化判断 比如layout不能为null
         */
        if(layout == null) {
            addWarn("Layout was not defined");
        }
        /**
         * 或者写入数据库 或者redis时 初始化连接等等
         */
        super.start();
    }

    @Override
    public void stop()
    {
        /**
         * 释放相关资源,如数据库连接,redis线程池等等
         */
        System.out.println("logback-stop方法被调用");
        if(!isStarted()) {
            return;
        }
        super.stop();
    }

    @Override
    public void append(ILoggingEvent event) {
        if (event == null || !isStarted()){
            return;
        }

        /**
         * 自定义日志输出的逻辑
         * 比如 操作数据库  redis kafka
         * 当然,我的本质目的是发钉钉消息
         */
        System.out.print("获取输出值"+event.getFormattedMessage());
        System.out.println("格式化输出日志:"+printString + ":" + layout.doLayout(event));
        System.out.println("==============================================  MyLogbackAppender要发消息了");
        //发钉钉消息: 具体处理逻辑,参考钉钉的文档
        //后续计划会开发一个 dingtalk-log-springboot-start 包

        try {
            OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
            text.setContent("这是一个测试");

            //https://oapi.dingtalk.com/robot/send?access_token=
            String accessToken = "{填入自己钉钉群自定义机器人的 webhook token}";
            String tokenURL = "https://oapi.dingtalk.com/robot/send?access_token=".concat(accessToken);
            DingTalkClient client = new DefaultDingTalkClient(tokenURL);
            OapiRobotSendRequest request = new OapiRobotSendRequest();
            request.setMsgtype("text");
            request.setText(text);

            //OapiRobotSendResponse response = client.execute(request);
        } catch (Exception e) {

        }
    }
}
           

2)、自定义Appender 继承AppenderBase<LoggingEvent> 

extends AppenderBase<LoggingEvent>
           
@Getter
@Setter
public class DingTalkAppender2 extends AppenderBase<LoggingEvent> {


    PatternLayoutEncoder encoder;


    @Override
    public void start() {
        if (this.encoder == null) {
            //name : logback.xml 中 appender 标签 配置的name值
            addError("No encoder set for the appender named [" + name + "].");
            return;
        }

        try {
            encoder.init(System.out);
        } catch (IOException e) {
        }
        super.start();
    }

    @Override
    public void stop() {
        //释放相关资源,如数据库连接,redis线程池等等
        System.out.println("stop方法被调用");
        if (!isStarted()) {
            return;
        }
        super.stop();
    }

    @Override
    protected void append(LoggingEvent eventObject) {
        Level level = eventObject.getLevel();

        /**
         * 指定只有 error 级别的日志,才发消息
         * 后续可以根据配置指定,此处暂不实现
         */
        if (level.ERROR.levelInt == level.levelInt) {
            System.out.println("DingTalkAppender2==============================================  要发钉钉消息了");
            /**
             * 发钉钉消息的逻辑,参看钉钉文档,
             * 后续计划会开发一个 dingtalk-log-springboot-start 包
             */

            try {
                OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
                text.setContent("告警任务:验证日志输出同时发钉钉消息");

                //https://oapi.dingtalk.com/robot/send?access_token=
                String accessToken = "{填入自己钉钉群自定义机器人的 webhook token}";
                String tokenURL = "https://oapi.dingtalk.com/robot/send?access_token=".concat(accessToken);
                DingTalkClient client = new DefaultDingTalkClient(tokenURL);
                OapiRobotSendRequest request = new OapiRobotSendRequest();
                request.setMsgtype("text");
                request.setText(text);

                OapiRobotSendResponse response = client.execute(request);
                System.out.println(JSONObject.toJSONString(response));
            } catch (Exception e) {

            }
        }
    }
}
           

3、自定义的Appender配置到logback.xml中

<appender name="DingTalkAppender2"
              class="com.xx.xx.xxx.DingTalkAppender2">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <!-- 日志收集最低日志级别 -->
            <level>ERROR</level>
        </filter>
        <encoder>
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <!-- 自定义参数 -->
        <!--<printString>DingTalkAppender2的logback日志输出</printString>-->
    </appender>

    <!-- 控制台输出 -->
    <appender name="DingTalkAppender"
              class="com.xx.xx.xx.xx.xx.DingTalkAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <!-- 日志收集最低日志级别 -->
            <level>INFO</level>
        </filter>
        <layout
                class="ch.qos.logback.classic.PatternLayout">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </layout>
        <!-- 自定义参数 -->
        <printString>DingTalkAppender的logback日志输出</printString>
    </appender>



        <!-- 把自定义的appender 配置到root 中 -->
<root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="DingTalkAppender"/>
        <appender-ref ref="DingTalkAppender2"/>
    </root>
           

4、启动项目正常输出日志,就能看到自定义日志的逻辑处理了。

参考博文:https://www.imooc.com/article/71184

继续阅读