springboot项目自定义日志输出,logback.xml使用自定义变量

背景

我一直对于自己做的学习项目中的日志输出不是很满意,想着对日志进行一个优化。

优化方向

1、将SQL日志单独提出来打印
2、加入traceId跟踪请求的走向,快速定位bug

MDC介绍

Logback的MDC(Mapped Diagnostic Context)提供了一种在多线程环境中跟踪特定信息的方法。 MDC用于在日志中存储上下文信息,并使该信息可用于整个请求处理的所有阶段,从而更好地诊断和调试问题。MDC使用一个映射表(类似于Java中的Map)来存储键值对,这些键值对可以是任何类型的数据,例如请求ID、用户ID、IP地址等。

当一个线程启动时,它可以将一个或多个键值对存储在MDC中。然后,在同一线程上运行的任何代码都可以轻松地访问这些键值对。例如,当处理Web请求时,可以将请求ID存储在MDC中,并在处理请求的每个阶段将其添加到日志记录中。这样,在日志中查看请求的整个处理过程时,可以很容易地跟踪请求ID。

在Logback中,可以使用MDC.put(key, value)方法向MDC添加键值对,使用MDC.get(key)方法获取键值对,使用MDC.remove(key)方法删除键值对。MDC的典型用法是在应用程序的入口点设置一些上下文信息,如请求ID、用户ID等,然后在应用程序中的任何地方记录这些信息。

话不多说,上代码

SQL日志单独打印

这个就是改一下logback.xml就行了
可以根据实际情况对于文件大小和保留天数进行修正
    <appender name="SQL-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/sql.log</file>

        <encoder>
            <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] %-5level %logger{50} -%msg%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>

        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${LOG_PATH}/sql/sql-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>150MB</maxFileSize>
            <!--日志文件保留天数-->
            <maxHistory>20</maxHistory>
        </rollingPolicy>

    </appender>

指定mybatis和mapper下的包打印到SQL-OUT

<logger name="org.mybatis" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="SQL-OUT"/>
    </logger>

    <logger name="com.shuizhao.easydatahub.mapper" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="SQL-OUT"/>
    </logger>

加入traceId

使用过滤器在MDC中放入自定义变量traceId即可
也可以放入请求的IP地址,登陆认证后的用户Id等

import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import java.io.IOException;
import java.util.UUID;

/**
 * @author shuizhao
 */
@Component
public class TraceIdFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 生成一个 traceId
        String traceId = (String) request.getAttribute("traceId");
        if (StringUtils.isBlank(traceId)) {
            traceId = UUID.randomUUID().toString();
            request.setAttribute("traceId", traceId);
        }
        // 设置到 MDC 中
        MDC.put("traceId", traceId);
        try {
            // 继续处理请求
            chain.doFilter(request, response);
        } finally {
            // 清空 MDC
            MDC.clear();
        }
    }
}


放入之后直接在logback.xml中使用%X{traceId}来调用即可

        <encoder>
            <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] %-5level %logger{50} -%msg%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>

完整的logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds">
    <property name="LOG_PATH" value="./logs"/>

    <appender name="INFO-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/tiny.log</file>

        <encoder>
            <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] %-5level %logger{50} -%msg%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>

        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${LOG_PATH}/tiny/tiny-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>150MB</maxFileSize>
            <!--日志文件保留天数-->
            <maxHistory>20</maxHistory>
        </rollingPolicy>

    </appender>

    <appender name="ERROR-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/error.log</file>

        <encoder>
            <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] %-5level %logger{50} -%msg%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>

        <!-- 只打印错误日志 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>

        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>100MB</maxFileSize>
            <!--日志文件保留天数-->
            <maxHistory>20</maxHistory>
        </rollingPolicy>

    </appender>

    <appender name="SQL-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/sql.log</file>

        <encoder>
            <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] %-5level %logger{50} -%msg%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>

        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${LOG_PATH}/sql/sql-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>150MB</maxFileSize>
            <!--日志文件保留天数-->
            <maxHistory>20</maxHistory>
        </rollingPolicy>

    </appender>

    <!-- 彩色日志 -->
    <!-- 彩色日志依赖的渲染类 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
    <conversionRule conversionWord="wex"
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
    <!-- 彩色日志格式 -->
    <property name="CONSOLE_LOG_PATTERN"
              value="${CONSOLE_LOG_PATTERN:-%clr(%d{HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr([%X{traceId}]){magenta} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
    <!--输出到控制台-->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- encoder defaults to ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
    </appender>


    <!--日志打印的包的范围,及分类日志文件存储 -->
    <logger name="com.shuizhao.easydatahub" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="INFO-OUT"/>
        <appender-ref ref="ERROR-OUT"/>
    </logger>

    <logger name="org.mybatis" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="SQL-OUT"/>
    </logger>

    <logger name="com.shuizhao.easydatahub.mapper" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="SQL-OUT"/>
    </logger>

    <root level="INFO">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="INFO-OUT"/>
        <appender-ref ref="ERROR-OUT"/>
    </root>

</configuration>

效果

cat tiny.log | grep ‘61f03cb1-8bb6-43e9-bc27-a0e705f9b3b4’
请求的切面日志
cat sql.log | grep ‘61f03cb1-8bb6-43e9-bc27-a0e705f9b3b4’
SQL日志

### 日志初始化错误分析 当遇到 `ch.qos.logback.classic.spi.ThrowableProxy` 初始化异常时,通常意味着日志框架配置存在问题或者依赖冲突。此类问题可能源于 Logback配置文件不正确或某些类加载失败。 #### 可能的原因及解决方案 1. **Logback 配置文件缺失或格式错误** 如果应用程序找不到有效的 logback.xml 或者该文件存在语法错误,则可能导致此异常。建议验证项目的资源路径下是否存在正确的 logback-spring.xml 文件,并确保其遵循标准 XML 语法规则[^1]。 2. **版本兼容性问题** 不同版本的 Spring BootLogback 库之间可能存在兼容性差异。检查项目中的依赖管理部分(如 pom.xml),确认使用spring-boot-starter-logging 版本与当前 Spring Boot 主版本相匹配[^3]。 3. **第三方库干扰** 某些情况下,引入了额外的日志实现(例如 SLF4J 绑定)可能会引起冲突。移除不必要的 logging provider 并仅保留官方推荐的一个即可解决问题。 4. **自定义配置不当** 对于那些修改过默认行为的应用程序来说,比如重写了 `SpringBootJoranConfigurator.addInstanceRules()` 方法,在这里添加实例规则的过程中如果处理不当也会引发上述提到的问题。因此应当仔细审查任何对原生功能所做的更改。 5. **环境变量影响** 环境设置也可能间接造成这类故障。特别是涉及到 JVM 参数 `-Dlogback.configurationFile=...` 来指定外部化配置的情况更需注意。确保这些参数指向合法可用的位置并且具有读取权限。 ```xml <!-- 示例:pom.xml 中声明合适的 starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </dependency> <!-- 示例:logback-spring.xml 结构片段 --> <configuration> <!-- 定义控制台输出器 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <!-- 设置根记录级别并关联到 STDOUT 输出器 --> <root level="info"> <appender-ref ref="STDOUT"/> </root> </configuration> ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值