SpringBoot 集成Logback实现rsyslog日志记录

SpringBoot 集成Logback实现rsyslog日志记录

代码搬运工
2021-08-21 / 1 评论 / 396 阅读 / 正在检测是否收录...
最近项目中需要将用户请求日志记录下来,打算通过Spring boot的logback将请求日志和一场数据通过发送到rsyslog,再通过rsyslog将日志发送到kafka中,之后就是消费处理就可以了。参考百度部分文章整理实现,个中问题欢迎指正,转载请指明出处 表情
引入springboot logging

  <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-logging</artifactId>
  </dependency>
新建logback-spring.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!--
说明:
    1. 文件的命名和加载顺序有关
       logback.xml早于application.yml加载,logback-spring.xml晚于application.yml加载
       如果logback配置需要使用application.yml中的属性,需要命名为logback-spring.xml
    2. logback使用application.yml中的属性
       使用springProperty才可使用application.yml中的值 可以设置默认值

-->
<configuration scan="true" scanPeriod="5 seconds" debug="false">
    <!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
    <!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
    <!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
    <!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->

    <!-- 从yml文件中读取配置-->
    <!-- rsyslog主机地址-->
    <springProperty scope="context" name="syslogHost" source="logback.rsyslog.host" defaultValue="10.221.2.77"/>
    <!-- rsyslog端口号-->
    <springProperty scope="context" name="syslogPort" source="logback.rsyslog.port" defaultValue="514"/>
    <!-- root日志级别-->
    <springProperty scope="context" name="rootLevel" source="logback.level.root" defaultValue="INFO"/>
    <!-- 业务代码的日志级别-->
    <springProperty scope="context" name="commonLevel" source="logback.level.common" defaultValue="DEBUG"/>

    <!-- 彩色日志 -->
    <!-- 配置格式变量:CONSOLE_LOG_PATTERN 彩色日志格式 -->
    <!-- magenta:洋红 -->
    <!-- boldMagenta:粗红-->
    <!-- cyan:青色 -->
    <!-- white:白色 -->
    <!-- magenta:洋红 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <!--withJansi>true</withJansi-->
        <encoder>
            <pattern>%boldCyan(%d{yyyy/MM/dd-HH:mm:ss}) [%thread] %highlight(%-5level) %logger- %msg%n %ex</pattern>
        </encoder>
    </appender>

   <!-- pattern配置参考https://www.cnblogs.com/jasenin/p/12692690.html -->
    <appender name="sysExceptionlog" class="ch.qos.logback.classic.net.SyslogAppender">
        <syslogHost>${syslogHost}</syslogHost>
        <port>${syslogPort}</port>
        <facility>local2</facility>
        <throwableExcluded>true</throwableExcluded>
        <suffixPattern>|{"type":"exception","date":"%d{yyyy/MM/dd HH:mm:ss}","level": "%level","class":"%logger","message": "%replace(%message){'\"', '\''}","requestId":"%X{requestId}","stackTrace": "%replace(%ex{short}){'\"', '\''}"}</suffixPattern>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
            <level>WARN</level>
        </filter>
    </appender>

    <appender name="sysRequestlog" class="ch.qos.logback.classic.net.SyslogAppender">
        <syslogHost>${syslogHost}</syslogHost>
        <port>${syslogPort}</port>
        <facility>local2</facility>
        <throwableExcluded>true</throwableExcluded>
        <suffixPattern>|{"type":"request","date":"%d{yyyy/MM/dd HH:mm:ss}","clientIp":"%X{clientIp}","requestId":"%X{requestId}","requestUrl":"%X{requestUrl}","requestMethod":"%X{requestMethod}","requestParam":"%X{requestParam}","requestBody":"%X{requestBody}","responseBody":"%X{responseBody}"}</suffixPattern>
    </appender>

    <appender name="asyncSysExceptionLog" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="sysExceptionlog" />
    </appender>

    <!--为了使日志记录对程序的正常运行产生影响,日志记录采用异步方式-->
    <appender name="asyncSysRequestLog" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="sysRequestlog" />
    </appender>

    <root level="${rootLevel}">
        <appender-ref ref="console"/>
        <appender-ref ref="asyncSysExceptionLog"/>
    </root>

    <logger name="com.demo" level="${commonLevel}" additivity="false">
        <appender-ref ref="console"/>
        <appender-ref ref="asyncSysExceptionLog"/>
    </logger>

    <logger name="com.demo.config.filter.RequestLogFilter" level="info" additivity="false">
        <appender-ref ref="asyncSysRequestLog"/>
    </logger>

</configuration>
自定义filter

自定义wrapper,获取响应值
package com.demo.config.wrapper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StreamUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @Title: RequestWrapper
 * @Description: 包装HttpServletRequest,目的是让其输入流可重复读
 * @Author: andy
 * @CreateDate: 2021/7/29 17:50
 * @Version: 1.0
 */
public class HttpServletRequestWrapper extends javax.servlet.http.HttpServletRequestWrapper {

    private static final Logger logger = LoggerFactory.getLogger(HttpServletRequestWrapper.class);
    /**
     * 用于保存读取body中数据
     */
    private byte[] body = null;

    public HttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        try {
            body = StreamUtils.copyToByteArray(request.getInputStream());
        } catch (IOException e) {
            logger.error("Wrap requestBody failed");
        }
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream() {

            @Override
            public int read() throws IOException {
                return bais.read();
            }

            @Override
            public boolean isFinished() {
                // TODO Auto-generated method stub
                return false;
            }

            @Override
            public boolean isReady() {
                // TODO Auto-generated method stub
                return false;
            }

            @Override
            public void setReadListener(ReadListener arg0) {
                // TODO Auto-generated method stub

            }
        };
    }
}
获取到日志信息
2021-08-20T12:08:40+08:00 DESKTOP-O6HS2C6 |{"type": "request","date":"2021/08/20 12:08:40","clientIp":"124.133.195.42","requestId":"83acb55394f74b40a5294c36a02cb778","requestUrl":"/demo/api/test","requestMethod":"GET","requestParam":"phone=19900002222","requestBody":"","responseBody":"{\"code\":\"S20003\",\"msg\":\"手机号不存在\"}"}

1

评论 (1)

取消