SpringBoot中使用TraceId进行日志追踪

**查询日志的痛点:**项目中每当我们查询日志的时候都是看前端请求什么接口,根据一些关键字进入服务器查询日志中是否有这个关键字,然而这个关键字在日志里面并不是唯一的,所以要生成一个唯一的标识,每一次请求都是唯一的一串字符,查询会过滤掉很多无用的信息,快捷查找到这次请求。为了解决这个痛点,就使用了TraceId。

一、TraceId 定义

用于标识某一次具体的请求ID。当用户的请求进入系统后,会在RPC调用网络的第一层生成一个全局唯一的traceId,并且会随着每一层的RPC调用,不断往后传递,这样的话通过traceId就可以把一次用户请求在系统中调用的路径串联起来。

在分布式系统中,一个请求可能会涉及多个服务和组件的调用,而traceId可以帮助我们追踪和查看整个请求的流程和调用链

二、TraceId的请求流程

在最开始请求系统时候生成一个全局唯一的traceId,放在http 请求header中,系统接收到请求后,从header中取出这个traceId,放入MDC中,这个traceId伴随着这整个请求的调用周期,即当一个服务调用另外一个服务的时候,需要将traceId往下传递,从而形成一条链路。

注意:这次的traceId主要是用UUID来生成的,前端生成traceId,后端拦截器拦截到了做一层判断,如果前端有,就不需要后端生成,而且只需要将前端的这个traceId发给后端人员,后端人员就能直接能定位到日志,不需要再让前端给请求的是什么接口,所以建议是前端来生成traceId。

三、SpringBoot整合TraceId

(一)添加一个logback.xml

logback.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration><property name="LOG_PATH" value="/xxx/log"/>  <!-- 项目的日志路径 --><property name="LOG_FILE" value="xxx"/><property name="DATE_PATH" value="${LOG_PATH}/%d{yyyy-MM-dd}"/><!-- 日志输出格式 --><property name="log.pattern.console"value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) [traceId:%X{traceId}] %highlight(%-5level) %boldMagenta(%logger{10}) - %cyan(%msg%n)"/><property name="log.pattern.file"value="%d{HH:mm:ss.SSS} [%thread] [traceId:%X{traceId}] %-5level %logger{20} - [%method,%line] - %msg%n"/><include resource="org/springframework/boot/logging/logback/defaults.xml"/><include resource="org/springframework/boot/logging/logback/console-appender.xml"/><!-- 控制台输出 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${log.pattern.console}</pattern><charset>utf8</charset></encoder></appender><!-- 日志文件fzwyapi-admin.log --><appender name="fileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${LOG_PATH}/${LOG_FILE}.log</file><append>true</append><encoder>
<!--            <pattern>${CONSOLE_LOG_PATTERN}</pattern>--><pattern>${log.pattern.file}</pattern></encoder><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><fileNamePattern>${DATE_PATH}/%i.log</fileNamePattern><maxHistory>15</maxHistory><totalSizeCap>20GB</totalSizeCap><maxFileSize>50MB</maxFileSize></rollingPolicy></appender><appender name="fileError" class="ch.qos.logback.core.rolling.RollingFileAppender"><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter><file>${LOG_PATH}/${LOG_FILE}.error.log</file><append>true</append><encoder><!--            <pattern>${CONSOLE_LOG_PATTERN}</pattern>--><pattern>${log.pattern.file}</pattern></encoder><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><fileNamePattern>${DATE_PATH}/%i.error.log</fileNamePattern><maxHistory>15</maxHistory><totalSizeCap>20GB</totalSizeCap><maxFileSize>50MB</maxFileSize></rollingPolicy></appender><root level="info"><appender-ref ref="fileAppender"/><appender-ref ref="fileError"/><appender-ref ref="STDOUT"/></root></configuration>

(二)添加TraceId工具类

TraceIdUtil.java

package xxx;import org.slf4j.MDC;import java.util.UUID;/*** @author lyc* @date 2024/10/17* @funtion*/
public class TraceIdUtil {public static final String TRACE_ID = "traceId";public static String getTraceId() {String traceId = MDC.get(TRACE_ID);return traceId == null ? "" : traceId;}public static void setTraceId(String traceId) {MDC.put(TRACE_ID, traceId);}public static void remove() {MDC.remove(TRACE_ID);}public static void clear() {MDC.clear();}public static String generateTraceId() {return UUID.randomUUID().toString().replace("-", "");}
}

(三)添加TraceId拦截器

SystemTraceIdInterceptor.java

package xxx;import xxx.TraceIdUtil;
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;/*** @author lyc* @date 2024/10/17* @funtion*/
@Component
public class SystemTraceIdInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {//如果有上层调用就用上层的IDString traceId = request.getHeader(TraceIdUtil.TRACE_ID);if (traceId == null) {traceId = TraceIdUtil.generateTraceId();}MDC.put(TraceIdUtil.TRACE_ID, traceId);//配置traceId到响应header中response.setHeader(TraceIdUtil.TRACE_ID, MDC.get(TraceIdUtil.TRACE_ID));return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {//调用结束后删除MDC.remove(TraceIdUtil.TRACE_ID);}
}

(四)InterceptorConfig配置TraceId拦截器

InterceptorConfig.java

package xxx.config;import xxx.SystemTraceIdInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import javax.annotation.Resource;/*** @author lyc* @updated: 2024/10/17* @funtion*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Resourceprivate SystemTraceIdInterceptor systemTraceIdInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//配置链路追踪traceId拦截器registry.addInterceptor(systemTraceIdInterceptor).addPathPatterns("/**");}}

四、效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/65363.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++类与对象上

1.面向过程和面向对象初步认识 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题 例如洗衣服&#xff1a; C是基于面向对象的&#xff0c;关注的是对象&#xff0c;讲一件事拆分成不同的对象&#xff0c;靠对…

向量组学习

向量组的秩及其线性组合 线性相关性 先看a1,a2 如果这两个向量不对应成比例的话,那必然内部不可能存在多余的向量,也就是无关. 主元所在的列都是独立向量 ,最大无关组就是b1,b2,b4,但这个是初等行变换后的,题目要的是A的,与之对应的就是a1,a2,a4 方程组解的结构

使用VS Code开发ThinkPHP项目

【图书介绍】《ThinkPHP 8高效构建Web应用》-CSDN博客 《ThinkPHP 8高效构建Web应用 夏磊 编程与应用开发丛书 清华大学出版社》【摘要 书评 试读】- 京东图书 ThinkPHP 8开发环境安装-CSDN博客 安装ThinkPHP项目的IDE 常用的集成开发环境&#xff08;IDE&#xff09;包括P…

软件耦合类型及相关说明

文字叙述太麻烦了&#xff0c;此内容个人觉得上图可能大家更容易接受。 ——话不多说&#xff0c;直接上图。

TestMAX/DFT Compiler:时序单元的类型、连接顺序和后DFT优化

相关阅读 TestMAX/DFT Compilerhttps://blog.csdn.net/weixin_45791458/category_12865937.html?spm1001.2014.3001.5482 时序单元的状态 未映射的时序单元(Unmapped Sequential Cell) 在Design Compiler读取了一个RTL设计后&#xff0c;Design Compiler内置的HDL Compiler工…

8086汇编(16位汇编)学习笔记06.串操作、流程转移指令

8086汇编(16位汇编)学习笔记06.串操作、流程转移指令-C/C基础-断点社区-专业的老牌游戏安全技术交流社区 - BpSend.net 串操作 源操作数使用si&#xff0c;默认段为DS&#xff0c;可段超越 目的操作数使用di&#xff0c;默认段为ES&#xff0c;不可段超越 串方向 串方向由D…

TCP off-path exploits(又一个弄巧成拙的例子)

承接前面几篇文章的观点&#xff0c;本文用一个安全攻击的例子说明为了解决一个伤害很低的低概率问题&#xff0c;会引入多么大的麻烦&#xff0c;这次是可怕的被攻击 (⊙o⊙)。 TCP 端口号只有 16bit&#xff0c;序列号只有 32bit&#xff0c;这意味着在强大攻击算力面前&…

YOLO11改进-注意力-引入自调制特征聚合模块SMFA

本篇文章将介绍一个新的改进机制——SMFA&#xff08;自调制特征聚合模块&#xff09;&#xff0c;并阐述如何将其应用于YOLOv11中&#xff0c;显著提升模型性能。随着深度学习在计算机视觉中的不断进展&#xff0c;目标检测任务也在快速发展。YOLO系列模型&#xff08;You Onl…

大表:适用于结构化数据的分布式存储系统

大家觉得有意义和帮助记得及时关注和点赞!!! 译者序摘要1 引言2 数据模型 2.1 行&#xff08;Row&#xff09;2.2 Column Families&#xff08;列族&#xff09; 2.2.1 设计2.2.2 column key 的格式&#xff1a;family:qualifier2.2.3 访问控制和磁盘/内存记账&#xff08;acco…

【AIGC-ChatGPT副业提示词指令 - 动图】魔法咖啡馆:一个融合创意与治愈的互动体验设计

引言 在当今快节奏的生活中&#xff0c;咖啡早已不仅仅是提神醒脑的饮品&#xff0c;更成为了一种情感寄托和生活态度的表达。本文将介绍一个独特的"魔法咖啡馆"互动体验设计&#xff0c;通过将咖啡与情感、魔法元素相结合&#xff0c;创造出一个充满想象力和治愈感…

xterm遇到的问题及解决方案

xterm遇到的问题及解决方案 /r插入终端导致的之后插入的数据覆盖了改行头部的数据 问题说明 如图所示&#xff0c;当在一行输入的候&#xff0c;输入的l插入到了改行的头部。 查看ws返回数据 可见ws返回的信息存在\r字符&#xff0c;在xterm.js中\r是回车字符的意思&…

Chrome被360导航篡改了怎么改回来?

一、Chrome被360导航篡改了怎么改回来&#xff1f; 查看是否被360主页锁定&#xff0c;地址栏输入chrome://version&#xff0c;看命令行end后面&#xff08;蓝色部分&#xff09;&#xff0c;是否有https://hao.360.com/?srclm&lsn31c42a959f 修改步骤 第一步&#xff1a…

blender中合并的模型,在threejs中显示多个mesh;blender多材质烘培成一个材质

描述&#xff1a;在blender中合并的模型导出为glb&#xff0c;在threejs中导入仍显示多个mesh&#xff0c;并不是统一的整体&#xff0c;导致需要整体高亮或者使用DragControls等不能统一控制。 原因&#xff1a;模型有多个材质&#xff0c;在blender中合并的时候&#xff0c;…

C语言----输入输出

目录 输入输出 1.按格式输入输出 2. 按格式输入 3. 按字符输入输出 输入&#xff1a; 输出&#xff1a; 垃圾字符回收 1. 通过空格回收 2. %*c 3.getchar&#xff08;&#xff09; 强制类型转换 输入输出 分为按格式输入输出和按字符输入输出 1.按格式输入输出 通…

计算机网络 (10)网络层

前言 计算机网络中的网络层&#xff08;Network Layer&#xff09;是OSI&#xff08;开放系统互连&#xff09;模型中的第三层&#xff0c;也是TCP/IP模型中的第二层&#xff0c;它位于数据链路层和传输层之间。网络层的主要任务是负责数据包从源主机到目的主机的路径选择和数据…

WebRTC服务质量(11)- Pacer机制(03) IntervalBudget

WebRTC服务质量&#xff08;01&#xff09;- Qos概述 WebRTC服务质量&#xff08;02&#xff09;- RTP协议 WebRTC服务质量&#xff08;03&#xff09;- RTCP协议 WebRTC服务质量&#xff08;04&#xff09;- 重传机制&#xff08;01) RTX NACK概述 WebRTC服务质量&#xff08;…

一维、线性卡尔曼滤波的例程(MATLAB)

这段 MATLAB 代码实现了一维线性卡尔曼滤波器的基本功能&#xff0c;用于估计在存在噪声的情况下目标状态的真实值 文章目录 一维线性卡尔曼滤波代码运行代码介绍1. **初始化部分**2. **数据生成**3. **卡尔曼滤波器实现**4. **结果可视化**5. **统计输出** 源代码 总结 一维线…

【Compose multiplatform教程13】【组件】Column和Row组件

查看全部组件文章浏览阅读495次&#xff0c;点赞17次&#xff0c;收藏12次。alignment。https://blog.csdn.net/b275518834/article/details/144751353 Column 功能说明&#xff1a;将子组件按照垂直方向依次排列&#xff0c;能够设置组件之间的间距、对齐方式等属性&#xff…

观察者模式和发布-订阅模式有什么异同?它们在哪些情况下会被使用?

大家好&#xff0c;我是锋哥。今天分享关于【观察者模式和发布-订阅模式有什么异同&#xff1f;它们在哪些情况下会被使用&#xff1f;】面试题。希望对大家有帮助&#xff1b; 观察者模式和发布-订阅模式有什么异同&#xff1f;它们在哪些情况下会被使用&#xff1f; 1000道 …

每天40分玩转Django:实操多语言博客

实操多语言博客 一、今日学习内容概述 学习模块重要程度主要内容国际化配置⭐⭐⭐⭐⭐基础设置、语言切换翻译模型⭐⭐⭐⭐⭐多语言字段、翻译管理视图处理⭐⭐⭐⭐多语言内容展示、URL处理前端实现⭐⭐⭐⭐语言切换、界面适配 二、模型设计 # models.py from django.db im…