Ver Fonte

线下兑现

malei05 há 3 semanas atrás
pai
commit
bfe6cd15ba

+ 1 - 0
pom.xml

@@ -52,6 +52,7 @@
 		<module>yyc-common-core</module>
 		<module>yyc-common-datasource</module>
 		<module>yyc-common-feign</module>
+		<module>yyc-common-log</module>
 		<module>yyc-common-gateway</module>
 		<module>yyc-common-gray</module>
 		<module>yyc-common-job</module>

+ 62 - 0
yyc-common-log/pom.xml

@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~
+  ~      Copyright (c) 2018-2025, hnqz All rights reserved.
+  ~
+  ~  Redistribution and use in source and binary forms, with or without
+  ~  modification, are permitted provided that the following conditions are met:
+  ~
+  ~ Redistributions of source code must retain the above copyright notice,
+  ~  this list of conditions and the following disclaimer.
+  ~  Redistributions in binary form must reproduce the above copyright
+  ~  notice, this list of conditions and the following disclaimer in the
+  ~  documentation and/or other materials provided with the distribution.
+  ~  Neither the name of the pig4cloud.com developer nor the names of its
+  ~  contributors may be used to endorse or promote products derived from
+  ~  this software without specific prior written permission.
+  ~  Author: hnqz
+  ~
+  -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>net.yyc.common</groupId>
+		<artifactId>yyc-common-parent</artifactId>
+		<version>1.0.0-SNAPSHOT</version>
+	</parent>
+
+	<artifactId>yyc-common-log</artifactId>
+	<packaging>jar</packaging>
+
+	<description>日志服务</description>
+
+
+	<dependencies>
+		<!--工具类核心包-->
+		<dependency>
+			<groupId>net.yyc.common</groupId>
+			<artifactId>yyc-common-core</artifactId>
+			<version>1.0.0-SNAPSHOT</version>
+		</dependency>
+		<dependency>
+			<groupId>net.yyc.common</groupId>
+			<artifactId>yyc-common-feign</artifactId>
+			<version>1.0.0-SNAPSHOT</version>
+		</dependency>
+		<!--安全依赖获取上下文信息-->
+		<dependency>
+			<groupId>org.springframework.security</groupId>
+			<artifactId>spring-security-core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.security.oauth</groupId>
+			<artifactId>spring-security-oauth2</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-sleuth</artifactId>
+		</dependency>
+	</dependencies>
+</project>

+ 69 - 0
yyc-common-log/src/main/java/net/yyc/common/log/LogAutoConfiguration.java

@@ -0,0 +1,69 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, hnqz All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: hnqz
+ *
+ */
+
+package net.yyc.common.log;
+
+import net.yyc.common.log.aspect.SysLogAspect;
+import net.yyc.common.log.aspect.SysLogHandler;
+import net.yyc.common.log.config.LogConfig;
+import net.yyc.common.log.event.SysLogListener;
+import lombok.AllArgsConstructor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+/**
+ * @author hnqz
+ * @date 2018/6/28
+ * <p>
+ * 日志自动配置
+ */
+@EnableAsync
+@Configuration
+@AllArgsConstructor
+@ConditionalOnWebApplication
+@Import(LogConfig.class)
+public class LogAutoConfiguration {
+
+    private final LogConfig logConfig;
+
+    @Bean
+    public SysLogAspect sysLogAspect(ApplicationEventPublisher publisher, SysLogHandler handler) {
+        return new SysLogAspect(publisher, handler);
+    }
+
+    @Bean
+    public SysLogListener sysLogListener(SysLogHandler handler) {
+        return new SysLogListener(handler);
+    }
+
+    @Bean
+    public FilterRegistrationBean<RequestLoggingFilter> requestLoggingFilter() {
+        RequestLoggingFilter filter = new RequestLoggingFilter(logConfig);
+        FilterRegistrationBean<RequestLoggingFilter> registration = new FilterRegistrationBean<>(filter);
+        registration.addUrlPatterns("/*");
+        registration.setOrder(Integer.MAX_VALUE);
+        return registration;
+    }
+
+}

+ 139 - 0
yyc-common-log/src/main/java/net/yyc/common/log/RequestLoggingFilter.java

@@ -0,0 +1,139 @@
+package net.yyc.common.log;
+
+import cn.hutool.core.util.CharsetUtil;
+import net.yyc.common.log.config.LogConfig;
+import net.yyc.common.log.vo.LogMessage;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.lang.NonNull;
+import org.springframework.util.StringUtils;
+import org.springframework.web.filter.OncePerRequestFilter;
+import org.springframework.web.util.ContentCachingRequestWrapper;
+import org.springframework.web.util.ContentCachingResponseWrapper;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * WEB请求日志数据拼装
+ *
+ */
+@Slf4j
+public class RequestLoggingFilter extends OncePerRequestFilter {
+
+    /**
+     * 请求EVENT
+     */
+    private static final String LOG_EVENT = "REQ";
+
+    /**
+     * 打印日志开关
+     */
+    private final boolean enable;
+
+    /**
+     * body最大长度
+     */
+    private final int maxLength;
+
+    private static final int LOGGING_BODY_MAX_LENGTH = 20 * 1024;
+
+    private static final String FILTER_ACTUATOR = "/actuator/";
+    private static final String FILTER_FAVICON = "/favicon.ico";
+
+	RequestLoggingFilter(LogConfig logConfig) {
+		this.enable = logConfig.isRequestEnable();
+		this.maxLength = logConfig.getRequestMaxLength();
+	}
+
+    /**
+     * 是否处理异步请求,false为处理
+     * <p>
+     * The default return value is "true", which means the filter will not be
+     * invoked during subsequent async dispatches. If "false", the filter will
+     * be invoked during async dispatches with the same guarantees of being
+     * invoked only once during a input within a single thread.
+     */
+    @Override
+    protected boolean shouldNotFilterAsyncDispatch() {
+        return false;
+    }
+
+    /**
+     * 核心方法,记录日志
+     */
+    @Override
+    protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response,
+                                    @NonNull FilterChain filterChain)
+            throws ServletException, IOException {
+        if (!enable || request.getRequestURI().startsWith(FILTER_ACTUATOR) || Objects.equals(request.getRequestURI(), FILTER_FAVICON)) {
+            filterChain.doFilter(request, response);
+            return;
+        }
+
+        long startTime = System.currentTimeMillis();
+        ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request, maxLength);
+        ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
+
+        try {
+            filterChain.doFilter(requestWrapper, responseWrapper);
+        } catch (Exception e) {
+            log.error("日志记录异常", e);
+            throw e;
+        } finally {
+            log.info(createMessage(requestWrapper, responseWrapper, startTime));
+            responseWrapper.copyBodyToResponse();
+        }
+    }
+
+    /**
+     * 拼接日志
+     */
+    private String createMessage(ContentCachingRequestWrapper request, ContentCachingResponseWrapper response, long startTime) {
+        LogMessage logMsg = new LogMessage();
+        logMsg.setEvent(LOG_EVENT + (isAsyncDispatch(request) ? "_ASYNC" : ""));
+        logMsg.setMethod(request.getMethod());
+        logMsg.setRequestUri(StringUtils.isEmpty(request.getQueryString()) ?
+                request.getRequestURI() : request.getRequestURI() + "?" + request.getQueryString());
+        logMsg.setIp(request.getRemoteAddr());
+        logMsg.setReqHeaders(assembleReqHeaders(request));
+        if (request.getContentLength() <= LOGGING_BODY_MAX_LENGTH) {
+            logMsg.setReqBody(new String(request.getContentAsByteArray(), CharsetUtil.CHARSET_UTF_8));
+        }
+        logMsg.setHttpStatus(response.getStatus());
+        logMsg.setRespHeaders(assembleRespHeaders(response));
+        if (response.getContentSize() <= LOGGING_BODY_MAX_LENGTH) {
+            logMsg.setRespBody(new String(response.getContentAsByteArray(), CharsetUtil.CHARSET_UTF_8));
+        }
+        logMsg.setDuration(System.currentTimeMillis() - startTime);
+        return logMsg.buildMessage();
+    }
+
+    private String assembleReqHeaders(HttpServletRequest request) {
+        StringBuilder sb = new StringBuilder();
+        Enumeration<String> enumeration = request.getHeaderNames();
+        while (enumeration.hasMoreElements()) {
+            String key = enumeration.nextElement();
+            sb.append(key).append("=").append(request.getHeader(key))
+                    .append(LogMessage.DEFAULT_LOG_FIELD_SEPARATOR_2);
+        }
+        if (sb.length() == 0) {
+            return null;
+        }
+        return sb.substring(0, sb.length() - 1);
+    }
+
+    private String assembleRespHeaders(HttpServletResponse response) {
+        return response.getHeaderNames().stream()
+                .map(
+                        key -> key + "=" + response.getHeader(key)
+                ).collect(
+                        Collectors.joining(LogMessage.DEFAULT_LOG_FIELD_SEPARATOR_2)
+                );
+    }
+}

+ 35 - 0
yyc-common-log/src/main/java/net/yyc/common/log/annotation/SysLog.java

@@ -0,0 +1,35 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, hnqz All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: hnqz
+ *
+ */
+
+package net.yyc.common.log.annotation;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface SysLog {
+
+	/**
+	 * 描述
+	 * @return {String}
+	 */
+	String value();
+
+}

+ 68 - 0
yyc-common-log/src/main/java/net/yyc/common/log/aspect/SysLogAspect.java

@@ -0,0 +1,68 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, hnqz All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: hnqz
+ *
+ */
+
+package net.yyc.common.log.aspect;
+
+import net.yyc.common.log.annotation.SysLog;
+import net.yyc.common.log.event.SysLogEvent;
+import lombok.AllArgsConstructor;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Objects;
+
+/**
+ * 操作日志使用spring event异步入库
+ *
+ * @author L.cm
+ */
+@Slf4j
+@Aspect
+@AllArgsConstructor
+public class SysLogAspect {
+    private final ApplicationEventPublisher publisher;
+    private final SysLogHandler handler;
+
+    @SneakyThrows
+    @Around("@annotation(sysLog)")
+    public Object around(ProceedingJoinPoint point, SysLog sysLog) {
+        String strClassName = point.getTarget().getClass().getName();
+        String strMethodName = point.getSignature().getName();
+
+        log.debug("[类名]:{},[方法]:{}", strClassName, strMethodName);
+        HttpServletRequest request = ((ServletRequestAttributes) Objects
+                .requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
+        Object[] args = point.getArgs();
+
+        long startTime = System.currentTimeMillis();
+        Object result = point.proceed();
+        long endTime = System.currentTimeMillis();
+        Object logEntity = handler.buildLogEntity(sysLog.value(), request, args, result, endTime - startTime);
+        publisher.publishEvent(new SysLogEvent(logEntity));
+        return result;
+    }
+
+}

+ 17 - 0
yyc-common-log/src/main/java/net/yyc/common/log/aspect/SysLogHandler.java

@@ -0,0 +1,17 @@
+package net.yyc.common.log.aspect;
+
+import javax.servlet.http.HttpServletRequest;
+
+public interface SysLogHandler {
+
+    /**
+     * 构建日志实体
+     */
+    Object buildLogEntity(String value, HttpServletRequest request, Object[] args, Object result, long costTime);
+
+    /**
+     * 保存日志
+     */
+    void saveLog(Object logEntity);
+
+}

+ 27 - 0
yyc-common-log/src/main/java/net/yyc/common/log/config/LogConfig.java

@@ -0,0 +1,27 @@
+package net.yyc.common.log.config;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+@Data
+@Configuration
+public class LogConfig {
+	/**
+	 * 配置关键字:请求日志开关
+	 */
+	@Value("${log.request.enable:true}")
+	private boolean requestEnable;
+
+	/**
+	 * 配置关键字:Feign请求日志开关
+	 */
+	@Value("${log.feign.enable:true}")
+	private boolean requestFeignEnable;
+
+	/**
+	 * 配置关键字:请求日志输出长度
+	 */
+	@Value("${log.request.maxLength:10240}")
+	private int requestMaxLength;
+}

+ 32 - 0
yyc-common-log/src/main/java/net/yyc/common/log/event/SysLogEvent.java

@@ -0,0 +1,32 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, hnqz All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: hnqz
+ *
+ */
+
+package net.yyc.common.log.event;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+
+@Getter
+@AllArgsConstructor
+public class SysLogEvent {
+
+    private final Object sysLog;
+
+}

+ 50 - 0
yyc-common-log/src/main/java/net/yyc/common/log/event/SysLogListener.java

@@ -0,0 +1,50 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, hnqz All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: hnqz
+ *
+ */
+
+package net.yyc.common.log.event;
+
+import cn.hutool.json.JSONUtil;
+import net.yyc.common.log.aspect.SysLogHandler;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.event.EventListener;
+import org.springframework.core.annotation.Order;
+import org.springframework.scheduling.annotation.Async;
+
+/**
+ * @author hnqz 异步监听日志事件
+ */
+@Slf4j
+@AllArgsConstructor
+public class SysLogListener {
+
+    private final SysLogHandler sysLogHandler;  // 业务侧注入
+
+    @Async
+    @Order
+    @EventListener(SysLogEvent.class)
+    public void saveSysLog(SysLogEvent event) {
+        try {
+            sysLogHandler.saveLog(event.getSysLog());
+        } catch (Exception e) {
+            log.error("审计日志保存失败, {}", JSONUtil.toJsonStr(event.getSysLog()), e);
+        }
+    }
+
+}

+ 26 - 0
yyc-common-log/src/main/java/net/yyc/common/log/init/ApplicationLoggerInitializer.java

@@ -0,0 +1,26 @@
+package net.yyc.common.log.init;
+
+import org.springframework.context.ApplicationContextInitializer;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.env.ConfigurableEnvironment;
+
+/**
+ * @author hnqz
+ * @date 2019-05-22
+ * <p>
+ * 初始化日志路径
+ */
+public class ApplicationLoggerInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
+
+	@Override
+	public void initialize(ConfigurableApplicationContext applicationContext) {
+		ConfigurableEnvironment environment = applicationContext.getEnvironment();
+
+		String appName = environment.getProperty("spring.application.name");
+
+		String logBase = environment.getProperty("LOGGING_PATH", "logs");
+		// spring boot admin 直接加载日志
+		System.setProperty("logging.file.name", String.format("%s/%s/debug.log", logBase, appName));
+	}
+
+}

+ 93 - 0
yyc-common-log/src/main/java/net/yyc/common/log/vo/LogMessage.java

@@ -0,0 +1,93 @@
+package net.yyc.common.log.vo;
+
+import cn.hutool.core.util.StrUtil;
+import lombok.Data;
+
+/**
+ * 收集日志的实体类
+ *
+ */
+@Data
+public class LogMessage {
+
+    /**
+     * 字段分隔符
+     */
+    private static final char DEFAULT_LOG_FIELD_SEPARATOR_1 = '\u0001';
+
+    /**
+     * 字段域内KV分隔符
+     */
+    public static final String DEFAULT_LOG_FIELD_SEPARATOR_2 = "&";
+
+    /**
+     * 占位符
+     */
+    private static final String DEFAULT_FIELD_PLACEHOLDER = "-";
+
+    /**
+     * 请求类型
+     */
+    private String event;
+
+    /**
+     * 请求方法
+     */
+    private String method;
+
+    /**
+     * 请求URI
+     */
+    private String requestUri;
+
+    /**
+     * 请求IP地址
+     */
+    private String ip;
+
+    /**
+     * 请求头
+     */
+    private String reqHeaders;
+
+    /**
+     * 请求消息体
+     */
+    private String reqBody;
+
+    /**
+     * 响应码
+     */
+    private int httpStatus;
+
+    /**
+     * 响应头
+     */
+    private String respHeaders;
+
+    /**
+     * 响应体
+     */
+    private String respBody;
+
+    /**
+     * 请求耗时
+     */
+    private long duration;
+
+    public String buildMessage() {
+        String[] strings = new String[]{
+                event,
+                method,
+                requestUri,
+                StrUtil.emptyToDefault(ip, DEFAULT_FIELD_PLACEHOLDER),
+                StrUtil.emptyToDefault(reqHeaders, DEFAULT_FIELD_PLACEHOLDER),
+                StrUtil.emptyToDefault(reqBody, DEFAULT_FIELD_PLACEHOLDER),
+                String.valueOf(httpStatus),
+                StrUtil.emptyToDefault(respHeaders, DEFAULT_FIELD_PLACEHOLDER),
+                StrUtil.emptyToDefault(respBody, DEFAULT_FIELD_PLACEHOLDER),
+                String.valueOf(duration)
+        };
+        return DEFAULT_LOG_FIELD_SEPARATOR_1 + String.join(String.valueOf(DEFAULT_LOG_FIELD_SEPARATOR_1), strings);
+    }
+}

+ 4 - 0
yyc-common-log/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,4 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+    net.yyc.common.log.LogAutoConfiguration
+org.springframework.context.ApplicationContextInitializer=\
+    net.yyc.common.log.init.ApplicationLoggerInitializer

+ 35 - 0
yyc-common-log/src/main/resources/com/qunzhixinxi/hnqz/common/log/request-logging-file-appender.xml

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<included>
+    <appender name="REQUEST_LOGGING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${log.path}/request-logging.log</file>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式 -->
+			<fileNamePattern>${log.path}/%d{yyyy-MM}/request-logging-%d{yyyy-MM-dd}-%i.log.gz</fileNamePattern>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+            <!-- 保留10天的日志 -->
+            <maxHistory>30</maxHistory>
+            <!--用来指定单个日志文件的上限大小,那么到了这个值,就会拆分日志-->
+            <maxFileSize>50MB</maxFileSize>
+        </rollingPolicy>
+        <!-- 追加方式记录日志 -->
+        <append>true</append>
+        <!-- 日志文件的格式 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+			<pattern>%date [%thread] %-5level [%X{traceId},%X{spanId}] [%logger{50}] %file:%line - %msg%n</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+        <!-- 此日志文件只记录info级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>info</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <logger name="net.yyc.common.log.RequestLoggingFilter" level="INFO" additivity="false">
+        <appender-ref ref="console" />
+        <appender-ref ref="REQUEST_LOGGING_FILE" />
+    </logger>
+</included>