Springboot-MDC+logback实现日志追踪

2023-11-04

一、MDC介绍

        MDC(Mapped Diagnostic Contexts)映射诊断上下文,该特征是logback提供的一种方便在多线程条件下的记录日志的功能。
        某些应用程序采用多线程的方式来处理多个用户的请求。在一个用户的使用过程中,可能有多个不同的线程来进行处理。典型的例子是 Web 应用服务器。当用户访问某个页面时,应用服务器可能会创建一个新的线程来处理该请求,也可能从线程池中复用已有的线程。在一个用户的会话存续期间,可能有多个线程处理过该用户的请求。这使得比较难以区分不同用户所对应的日志。当需要追踪某个用户在系统中的相关日志记录时,就会变得很麻烦。
        MDC正是用于解决上述问题的,MDC 可以看成是一个与当前线程绑定的哈希表,可以往其中添加键值对。MDC 中包含的内容可以被同一线程中执行的代码所访问。当前线程的子线程会继承其父线程中的 MDC 的内容。当需要记录日志时,只需要从 MDC 中获取所需的信息即可。MDC 的内容则由程序在适当的时候保存进去。对于一个 Web 应用来说,通常是在请求被处理的最开始保存这些数据。

二、MDC实现日志跟踪

        一个系统提供服务,提供给其他系统来调用,当其他系统调用的时候,请求头带上唯一的请求标识(requestId),把这个requestId输出到日志中,这样两个系统直接就会形成一个执行链,用requestId串联起来,当出现错误时,可以在调用方查询对应的请求日志,也可以在服务方查询请求日志,定位问题很方便,输出日志的地方很多。可以使用MDC配合logback中的pattern。

三、HandlerInterceptor拦截器

相关介绍:

SpringBoot使用过滤器、拦截器、切面(AOP),及其之间的区别和执行顺序 - 劈天造陆 - 博客园
HandlerInterceptor_dekulugu的博客-CSDN博客_handlerinterceptor

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class TokenInterceptor implements HandlerInterceptor {
    private static final Logger logger = LoggerFactory.getLogger(TokenInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        //添加MDC日志
        String appkey = request.getHeader("appkey");
        MDC.put("logTrackId", appkey);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        //移除MDC日志
        MDC.remove("logTrackId");
    }

}

四、logback文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <property name="logLevel" value="INFO"></property>
    <property name="logPath" value="./logs"></property>
    <property name="maxHistory" value="31"/>
    <property name="maxFileSize" value="100MB"/>
    <property name="totalSizeCap" value="200GB"/>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] [%X{logTrackId}] %-5level %logger{35} - %msg %n</pattern>
        </encoder>
    </appender>

    <appender name="FILE_INFO" class="ch.qos.logback.classic.sift.SiftingAppender">
        <!--discriminator鉴别器,根据logTrackId这个key对应的value鉴别日志事件,然后委托给具体appender写日志-->
        <discriminator>
            <key>logTrackId</key>
            <defaultValue>default</defaultValue>
        </discriminator>
        <sift>
            <!--具体的写日志appender,每一个logTrackId创建一个文件-->
            <appender name="FILE-${logTrackId}" class="ch.qos.logback.core.rolling.RollingFileAppender">
                <!--直接指定文件路径-->
                <append>true</append>
                <encoder charset="UTF-8">
                    <pattern>%d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] [%X{logTrackId}] %-5level %logger{35} - %msg%n</pattern>
                </encoder>
                <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
                    <!--定义文件滚动时的文件名的格式-->
                    <fileNamePattern>${logPath}/%d{yyyy-MM-dd}/${logTrackId}-%i.log</fileNamePattern>
                    <maxHistory>${maxHistory}</maxHistory>
                    <maxFileSize>${maxFileSize}</maxFileSize>
                    <totalSizeCap>${totalSizeCap}</totalSizeCap>
                </rollingPolicy>
                <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                    <level>INFO</level>
                </filter>
            </appender>
        </sift>
    </appender>

    <!-- 异步输出 -->
    <appender name="ASYNC-INFO" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <queueSize>512</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="FILE_INFO"/>
    </appender>

    <root level="${logLevel}">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="FILE_INFO"/>
    </root>
</configuration>

相关学习链接:

logback新认识(二):logback之MDC日志跟踪、日志自定义效果_IT-CRUD-CSDN博客

【日志追踪】(微服务应用和单体应用)-logback中的MDC机制 - 听风是雨 - 博客园

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Springboot-MDC+logback实现日志追踪 的相关文章

随机推荐

  • C++全局变量被多次析构导致程序崩溃的问题

    问题描述 1 在静态库libxxx a中定义了一个全局的string对象 2 有多个so文件都连接了这个静态库 并且引用了这个全局变量 3 有一个程序同时加载了多个上述的so文件 4 在这个程序退出时 全局的string就会被多次析构 5
  • vue正式环境与测试环境压包配置方法

    1 安装cross env cnpm install save dev cross env package json配置修改 这里分别添加env config prod env config dev来控制当前的压包环境 package js
  • 互联网网站的反爬虫策略浅析

    因为搜索引擎的流行 网络爬虫已经成了很普及网络技术 除了专门做搜索的Google Yahoo 微软 百度以外 几乎每个大型门户网站都有自己的搜索引擎 大大小小叫得出来名字得就几十种 还有各种不知名的几千几万种 对于一个内容型驱动的网站来说
  • org.springframework.context.annotation.ConflictingBeanDefinitionException异常处理

    问题描述 项目启动时 报了这个错 org springframework context annotation ConflictingBeanDefinitionException 标记为Bean类 com gaotai zhxy prop
  • 在vmware环境下安装ubuntu

    在vmware环境下安装ubuntu18 04 1 下载VMware workstation16 2 下载ubuntu 18 04 5 3 安装vmware 创建虚拟机 一 VMware workstation16 下载链接 https p
  • 10、CLASSIFIER-FREE DIFFUSION GUIDANCE

    简介 论文 https arxiv org pdf 2207 12598 pdf 分类器指导将扩散模型的得分估计与图像分类器的梯度相结合 因此需要训练与扩散模型分开的图像分类器 实验证明 在没有分类器的情况下 指导确实可以由纯生成模型执行
  • sed全文字符串替换

    sed i s 被替换的内容 要替换成的内容 file sudo sed i s archive ubuntu mirrors aliyun etc apt sources list
  • 抖音rpc调用生成x-gorgon、x-argus签名学习记录

    一 通过jadx gui分析apk 找到签名入口函数如下 先hook下这个函数 能看到有结果 接下来就是构造参数模拟调用就行 有两个参数 第一个是url的拼接 第二个是headers里面的一些参数构成的map 这个参数每个接口可能不一样 我
  • 若依ruoyi改皮肤-主题(二)

    一 风格等基础设置 有深色和浅色风格两种 根据设计图考虑是否需要 如果不需要 去掉一种风格 这里以浅色风格为主 在 布局设置 里 可以设置主题风格 深浅 主题颜色 直接下拉修改主色 隐藏菜单 顶部标签等等 如果想在css里修改 1 主题风格
  • 30套JSP网站源代码合集

    JSP技术是以Java语言作为脚本语言的 JSP网页为整个服务器端的Java库单元提供了一个接口来服务于HTTP的应用程序 我收集了一些JSP开发的网站源代码 从实践中学习 希望对大家有用 资料名称 下载地址 网上购物系统 jsp mysq
  • 原根

    定义 在数论 特别是整除理论中 原根是一个很重要的概念 对于两个正整数 由欧拉定理可知 存在正整数 比如说欧拉函数 即小于等于的正整数中与互素的正整数的个数 使得 由此 在时 定义对模的指数 为使 成立的最小的正整数 由前知 一定小于等于
  • nodejs接收form-data数据

    nodejs接收form data类型的数据 不能使用body parser来解析接收 multiparty有多个监听方法 这只是其中一种 var multiparty require multiparty var fs require f
  • 软件压力测试和性能测试分析方法论

    压测和性能分析方法论 性能测试基础 性能测试的常见分类 性能测试 用来验证系统的性能是否满足设计的预期 一般来说对系统的压力会比较小 不会压垮系统 只是进行简单的验证 负载测试 通过不断施加负载压力 寻找系统最优的处理能力 最好的性能状态
  • 北京题库插件:没法登陆又何妨?

    背景介绍 什么是北京题库 北京题库 是专注于中小学教学产品研发的教研平台 拥有试卷 资料等优质资源 致力于为教师备课 教研提供一站式服务 百度百科 简单来说 收录的很多资料 相对好用一点 但是 其使用是有一定限制的 比如网页端必须要微信扫码
  • void与void*

    void与void void关键字的使用规则 1 如果函数没有返回值 那么应声明为void类型 2 如果函数无参数 那么应声明其参数为void 3 如果函数的参数可以是任意类型指针 那么应声明其参数为void 4 void不能代表一个真实的
  • SISD、MIMD、SIMD、MISD计算机的体系结构的Flynn分类法

    1 计算平台介绍 Flynn于1972年提出了计算平台的Flynn分类法 主要根据指令流和数据流来分类 共分为四种类型的计算平台 如下图所示 单指令流单数据流机器 SISD SISD机器是一种传统的串行计算机 它的硬件不支持任何形式的并行计
  • Elasticsearch 开启https鉴权

    Elasticsearch 早期的版本配置鉴权 由于插件收费 所以配置起来比较麻烦 但是最近发现Elasticsearch的8 2版本中可以配置https及鉴权的操作 所以记录一下给想要获取该知识的人 分享一下 第一步 修改elastics
  • Android开发屏幕适配方案

    由于Android系统的开放性 任何用户 开发者 硬件厂商和运营商都可以对Android系统和硬件进行定制 修改成他们自己所需要的样子 使得随着Android设备的增多 设备碎片化 系统碎片化 屏幕尺寸碎片化和屏幕碎片化的程度也在不断加深
  • 竞赛知识点4【搜索】

    文章目录 复习 栈和队列的概念 树 1 1 深度优先搜索 dfs 1 1 1 概念 1 1 2 例题 1 输出n个数的全排列 2 输出n个数中选m个的组合 3 N皇后 8皇后的升级版 4 马踏棋盘 1 1 3 DFS大体框架 1 1 4 剪
  • Springboot-MDC+logback实现日志追踪

    一 MDC介绍 MDC Mapped Diagnostic Contexts 映射诊断上下文 该特征是logback提供的一种方便在多线程条件下的记录日志的功能 某些应用程序采用多线程的方式来处理多个用户的请求 在一个用户的使用过程中 可能