Springboot实现链路追踪功能

news2025/2/25 8:42:51

前言

在日常开发中,一个业务的实现往往会调用很多个方法,当我们去看日志的时候,各种接口的日志打印出来,看着就头疼,压根没办法去定位,而链路追踪就能很好的帮助我们去查看接口从头至尾依次调用了哪些方法。

同时我们还可以通过链路追踪的traceId去日志文件中去定位问题,比如:

grep   'c03ed014b9b34252b872009d030904f7'    log.log
或者
# 查看上下5行
grep -5   'c03ed014b9b34252b872009d030904f7'    log.log

如图所示:
在这里插入图片描述

实现代码

本案例实现是通过springboot默认日志logback实现。

第一步:导入Maven依赖

    <!--lombok配置-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.10</version>
    </dependency>

第二步:添加整合logback,打印日志,logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds">
    <contextName>logback</contextName>
    <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
    <springProperty scope="context" name="log.path" source="log.path"/>
 <!-- 彩色日志 -->
    <!-- 彩色日志依赖的渲染类 -->
    <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="[traceId:%X{traceId}] ${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>

    <property name="PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"/> 	
    <!--输出到控制台-->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>debug</level>
        </filter>
        <encoder>
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <!-- 设置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <!-- 滚动文件输出日志 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/log.log</file>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${log.path}/log-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${PATTERN}</pattern>
        </encoder>
    </appender>
 
    <root level="INFO">
        <!-- 配置日志输出的方式,可以同时输出到控制台和文件 -->
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
    </root>
</configuration>

第三步:application.yml中需要指定logback-spring.xml

logging:
  config: classpath:logback-config.xml

第四步:自定义日志拦截器 LogInterceptor
作用:每一次接口调用时,从线程维度上添加链路ID–traceId。


import com.alibaba.druid.util.StringUtils;
import com.dinglianshuke.ipfs.service.common.utils.MDCTraceUtil;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * @author o
 * @description 自定义日志拦截器
 * @date 2024/4/11
 *
 */
public class LogInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 客户端可以传入链路ID,需要唯一性
        String traceId = request.getHeader(MDCTraceUtil.TRACE_ID_HEADER);
        if (!StringUtils.isEmpty(traceId)) {
            MDCTraceUtil.putTrace(request.getHeader(MDCTraceUtil.TRACE_ID_HEADER));
        } else {
            MDCTraceUtil.addTrace();
        }
        return true;
    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        MDCTraceUtil.removeTrace();
    }
}

这边将MDC提取出来做成了一个工具类MDCTraceUtil:

import org.slf4j.MDC;
import java.util.UUID;

public class MDCTraceUtil {
    /**
     * 追踪id的名称
     */
    public static final String KEY_TRACE_ID = "traceId";

    /**
     * 日志链路追踪id信息头
     */
    public static final String TRACE_ID_HEADER = "x-traceId-header";


    /**
     * 创建traceId并赋值MDC
     */
    public static void addTrace() {
        String traceId = createTraceId();
        // MDC(Mapped Diagnostic Context)诊断上下文映射,是@Slf4j提供的一个支持动态打印日志信息的工具。
        MDC.put(KEY_TRACE_ID, traceId);
    }

    /**
     * 赋值MDC
     */
    public static void putTrace(String traceId) {
        MDC.put(KEY_TRACE_ID, traceId);
    }

    /**
     * 获取MDC中的traceId值
     */
    public static String getTraceId() {
        return MDC.get(KEY_TRACE_ID);
    }

    /**
     * 清除MDC的值
     */
    public static void removeTrace() {
        MDC.remove(KEY_TRACE_ID);
    }

    /**
     * 创建traceId
     */
    public static String createTraceId() {
        return UUID.randomUUID().toString().replace("-", "");
    }

}

第五步:新增LogWebMvcConfig,添加拦截器

import com.dinglianshuke.ipfs.service.common.interceptor.LogInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;


@Configuration
public class LogWebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 添加拦截器
        registry.addInterceptor(mvcInterceptor())
                // 拦截所有请求的路径
                .addPathPatterns("/**");
    }

    @Bean
    public LogInterceptor mvcInterceptor() {
        return new LogInterceptor();
    }

}

之后就是编写接口,启动测试即可。
在这里插入图片描述

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

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

相关文章

CSS导读 (元素显示模式)

&#xff08;大家好&#xff0c;今天我们将继续来学习CSS的相关知识&#xff0c;大家可以在评论区进行互动答疑哦~加油&#xff01;&#x1f495;&#xff09; 目录 三、CSS的元素显示模式 3.1 什么是元素显示模式 3.2 块元素 3.3 行内元素 3.4 行内块元素 3.5 元素…

ssm“健康早知道”微信小程序

采用技术 ssm“健康早知道”微信小程序的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringMVCMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 需求分析 利用ssm、Java、MyEclipse和mysql数据库等知识点&#xff0c;结合相关设…

五一出游 请带上我。必备全家桶。出游变成搬家。千里快递员,这样的人就不要带了。学习过后,你会使用这些句子了吗?

五一出游&#xff0c;即劳动节假期出游&#xff0c;需要准备的物品会根据旅行的目的地、天气状况、交通方式和个人习惯有所不同。以下是一个基本的全家桶必备物品清单&#xff1a; 一、 证件类&#xff1a; 身份证驾驶证&#xff08;如果自驾&#xff09;护照/港澳通行证/台…

C语言学习笔记之操作符篇

目录 算术运算符 移位操作符 整型在内存中的存储&#xff08;补充知识&#xff09; ​编辑左移操作符 右移操作符 位操作符 赋值操作符 复合赋值操作符 单目操作符 关系操作符 逻辑操作符 && 与 || 的计算特点 条件操作符 逗号表达式 下标引用操作符 函…

在linux上面安装xxl-job2.4.0

问题 由于预算有限&#xff0c;用不起lambda去跑定时任务&#xff0c;现在只能在EC2上面自己安装一个单机版的xxl-job了。 步骤 下载压缩包 在这个页面下载压缩包&#xff0c;并本地解压。 https://github.com/xuxueli/xxl-job/releases mysql准备 找到它默认身数据库初始…

Unity(MVC思想)

MVC 一下演示使用MVC和不使用MVC的做法区别。 前两个没有使用MVC 主面板逻辑&#xff1a; mainPanel是该脚本名字 每个场景中不一定存在该面板&#xff0c;单纯的显隐需要去手动挂载过于麻烦。 所以自己读取创建面板出来(每个场景仅创建一次)&#xff0c;存下该面板&#xf…

ubuntu系统安装python虚拟环境

一、安装python&#xff1a; 步骤1&#xff1a;在Ubuntu系统中打开终端&#xff0c;你可以使用快捷键CtrlAltT来打开终端&#xff0c;或者在应用程序菜单中找到终端。 步骤2&#xff1a;更新软件包列表&#xff0c;在终端中输入以下命令&#xff0c;更新软件包列表&#xff1…

React 快速入门:掌握前端开发的核心技能

React 快速入门&#xff1a;掌握前端开发的核心技能 一、React 简介1.1 React 的历史1.2 React 的概念1.3 React 的特点1.4 React 的官网地址 二、开发环境搭建三、React 基础3.1 JSX3.2 组件3.3 Props3.4 State3.5 props 和 state 的区别3.6 Hook 四、React 生命周期五、添加样…

oracle分区表迁移后空间占用增大

检查分区段隐含参数&#xff1a; select a.KSPPINM "Parameter", c.ksppstvl "Instance Value", ksppdesc "Desc" from sys.x$ksppi a, sys.x$ksppcv b, sys.x$ksppsv c where a.indx b.indx and a.indx c.indx and substr(ksppinm,1,1)_ and…

AI证件照抠图

AI证件照抠图 AI证件照抠图1. 环境导入2. main.py3. 实现效果展示 AI证件照抠图 *免费AI证件照抠图 1. 环境导入 mkdir /home/aistudio/external-libraries pip install onnxruntime scikit-image -i https://mirrors.aliyun.com/pypi/simple/ \-t /home/aistudio/external…

Mysql【索引覆盖、索引下推、索引合并、索引跳跃】介绍

索引覆盖、索引下推、索引合并、索引跳跃都是Mysql对索引的优化手段&#xff0c;它们的思想就是尽量让查询数据走索引&#xff0c;那它们有什么区别呢&#xff1f; 一、首先介绍一下MySQL体系结构 上图来自MySQL官方文档。 通常把MySQL从上至下分为以下几层&#xff1a; MySQ…

arXiv苹果公司新论文“Self-Play”方法训练车辆道路merge的策略

arXiv苹果公司新论文“Self-Play”方法训练车辆道路merge的策略 附赠自动驾驶学习资料和量产经验&#xff1a;链接 苹果于2020年1月28日上传arXiv新论文“Towards Learning Multi-agent Negotiations via Self-Play“。 摘要&#xff1a; 做出复杂、鲁棒和安全的串行决策是智能…

使用 Python 的 LSTM 进行股市预测

目录 一、说明 二、为什么需要时间序列模型&#xff1f; 三、下载数据 3.1 从 Alphavantage 获取数据 3.1 从 Kaggle 获取数据 3.3 数据探索 3.4 数据可视化 四、将数据拆分为训练集和测试集 五、数据标准化 六、通过平均进行一步预测 6.1 标准平均值 6.2 指数移动平均线 6.3 如…

包拯断案 | 集群备份续集:三招解决定时备份延迟@还故障一个真相

今天&#xff0c;小编给大家讲述自己亲身遇到的一个数据库集群备份问题&#xff0c;希望帮助DBA运维的你绕开这个烦恼&#xff0c;轻松找到答案&#xff01; 1、数据库集群在进行定时备份时&#xff08;从节点备份&#xff09;&#xff0c;出现了主从延迟较大的告警&#xff0c…

泽众Testone自动化测试平台,测试用例支持单个调试执行,同步查看执行日志

泽众Testone自动化测试平台之前版本&#xff0c;测试用例批量和单个执行&#xff0c;必须要通过测试集操作执行&#xff0c;操作略繁琐&#xff0c;我们通过本轮优化升级&#xff0c;测试用例直接可以单个调试执行&#xff0c;同步查看执行日志&#xff0c;操作上去繁就简&…

Windows搭建Jellyfin影音服务结合内网穿透实现公网访问本地视频文件

文章目录 1. 前言2. Jellyfin服务网站搭建2.1. Jellyfin下载和安装2.2. Jellyfin网页测试 3.本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5. 结语 1. 前言 随着移动智能设备的普及&#xff0c;各种各样的使用需求也被开发出来&…

windows ffmpeg7 通过rtsp拉取h265裸流

点击下边那个链接会转到github 下载完成后&#xff0c;添加include、lib到工程。 添加头文件&#xff1a; extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavformat/avio.h" #inclu…

总体标准差、样本标准差、标准误(标准误差)

下面是样例&#xff1a; 参考文章如何做好SCI论文中的标准误差图 - 知乎 (zhihu.com)

鸿蒙HarmonyOS 与 Android 的NDK有什么不一样?

鸿蒙&#xff08;HarmonyOS&#xff09;和Android的NDK&#xff08;Native Development Kit&#xff09;是两个不同的概念&#xff0c;它们在设计理念、架构、开发方式和目标平台等方面存在着一些显著的不同。让我们详细比较它们的特点和区别。 1. 设计理念和架构&#xff1a; …

雪亮工程视频联网综合管理/视频智能分析系统建设方案(二)

一、我国雪亮工程当前建设需求 1&#xff09;加强社会治安防控感知网络建设 加强社会治安防控智能感知网络建设&#xff0c;针对城中村、背街小巷、城乡结合部等重点区域建设安装视频监控设备&#xff0c;减少死角和盲区&#xff0c;与已有感知系统结合&#xff0c;形成高低搭…