找企业网站制作,黑龙江省建设工程交易中心网站,汕头网页,wordpress 做一个视频站前后端拦截器MDC实现纯数字 traceId 全链路日志追踪#xff08;axios Spring Boot 超详细实战#xff09;
前言
在现代前后端分离的项目中#xff0c;traceId#xff08;追踪 ID#xff09; 是定位线上问题、串联日志链路的利器。合理设计和自动化传递 traceId#xf…前后端拦截器MDC实现纯数字 traceId 全链路日志追踪axios Spring Boot 超详细实战
前言
在现代前后端分离的项目中traceId追踪 ID 是定位线上问题、串联日志链路的利器。合理设计和自动化传递 traceId可以极大提升排查效率和开发体验。本文将手把手教你如何用 axios 和 Spring Boot 的拦截器在前后端自动生成、传递和打印纯数字 traceId并结合日志框架MDC实现真正的全链路日志追踪。 一、什么是 traceId为什么要用 traceId
traceId 是一次请求在系统中流转的唯一标识。无论是前端页面操作、后端接口调用还是微服务之间的链路追踪traceId 都能把相关日志串联起来。
主要作用
快速定位问题出错时只需查 traceId就能串联起前后端、数据库、第三方服务的所有日志。方便检索纯数字 traceId 在日志平台、数据库、监控系统中检索更友好。开发调试本地调试、线上排查都能一键定位。 二、技术选型与方案设计
1. 纯数字 traceId 的优势
易于检索在 Kibana、ELK、数据库等平台纯数字比字母符号更好查找。便于人工输入有时候需要手动输入 traceId 检索纯数字更友好。兼容性好部分系统或中间件对 header 字段有字符集限制纯数字更保险。
2. 技术选型
前端用 nanoid 生成纯数字 traceIdaxios 拦截器自动添加到每个请求头。后端Spring Boot 拦截器统一获取 traceId自动打印到日志必要时生成后端 traceId。日志框架MDC用 logback/log4j2 等日志框架结合 MDCMapped Diagnostic Context让所有日志自动带上 traceId。 三、前端实现axios 拦截器自动添加 traceId
1. 安装依赖
npm install axios nanoid
# 或
yarn add axios nanoid2. 配置 axios 拦截器
// src/utils/traceId.js
import { customAlphabet } from nanoid;// 生成16位纯数字 traceId
export const generateTraceId customAlphabet(0123456789, 16);// src/utils/axios.js
import axios from axios;
import { generateTraceId } from ./traceId;// 创建 axios 实例
const instance axios.create({// baseURL: http://your-api-url.com, // 可配置timeout: 10000
});// 请求拦截器自动添加 traceId
instance.interceptors.request.use(config {const traceId generateTraceId();config.headers[traceId] traceId;// 也可以在这里打印日志方便调试console.log([traceId${traceId}] ${config.method?.toUpperCase()} ${config.url});// 可选把 traceId 挂到 config 方便响应拦截器用config.traceId traceId;return config;
}, error {return Promise.reject(error);
});// 响应拦截器可统一处理 traceId 相关逻辑
instance.interceptors.response.use(response {// 可选打印响应日志// console.log([traceId${response.config.traceId}] 响应:, response.data);return response;
}, error {// 可选打印错误日志// if (error.config error.config.traceId) {// console.error([traceId${error.config.traceId}] 请求出错:, error);// }return Promise.reject(error);
});export default instance;3. 使用 axios 实例
// src/api/demo.js
import axios from ../utils/axios;export function getHello() {return axios.get(/api/hello);
}四、后端实现Spring Boot 拦截器统一处理 traceId
1. 新建 TraceIdInterceptor
// src/main/java/com/example/demo/interceptor/TraceIdInterceptor.java
package com.example.demo.interceptor;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 TraceIdInterceptor implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {String traceId request.getHeader(traceId);if (traceId null || traceId.isEmpty()) {traceId generateServerTraceId();}// 设置到 MDC所有日志自动带 traceIdMDC.put(traceId, traceId);// 也可以设置到 request attribute后续 Controller 需要时可用request.setAttribute(traceId, traceId);return true;}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {// 请求结束后清理 MDC防止线程复用污染MDC.remove(traceId);}private String generateServerTraceId() {long timestamp System.currentTimeMillis();int random (int)(Math.random() * 1000000);return String.format(%d%06d, timestamp, random);}
}2.注册拦截器
// src/main/java/com/example/demo/config/WebConfig.java
package com.example.demo.config;import com.example.demo.interceptor.TraceIdInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
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 WebConfig implements WebMvcConfigurer {Autowiredprivate TraceIdInterceptor traceIdInterceptor;Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(traceIdInterceptor).addPathPatterns(/**);}}3.Controller 示例
// src/main/java/com/example/demo/controller/HelloController.java
package com.example.demo.controller;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;RestController
public class HelloController {private static final Logger logger LoggerFactory.getLogger(HelloController.class);GetMapping(/api/hello)public String hello(HttpServletRequest request) {String traceId (String) request.getAttribute(traceId);// 业务日志logger.info(业务处理逻辑);return {\code\:0, \msg\:\ok\, \traceId\:\ traceId \};}}
五、什么是 MDC为什么要用 MDC
1. MDCMapped Diagnostic Context简介
MDC映射诊断上下文是日志框架如 logback、log4j2提供的一种机制可以为当前线程绑定一些上下文信息如 traceId、userId、ip 等这些信息会自动出现在日志输出中。
主要特点
线程隔离MDC 绑定在当前线程不会串日志适合 Web 请求等多线程场景。自动注入只需在请求入口如拦截器设置一次 traceId后续所有日志都自动带上 traceId。日志格式统一所有日志包括第三方库、异常栈等都能自动带上 traceId方便检索和分析。
2. MDC 的好处
自动化避免每条日志手动拼接 traceId减少遗漏和冗余代码。统一性日志格式统一便于团队协作和平台检索。易于检索方便后续用 ELK、Kibana、Sentry 等平台检索和分析。线程安全MDC 绑定在当前线程不会出现 traceId 串日志的问题。
3. 为什么不用手动拼接 traceId
手动拼接容易遗漏代码冗余。用 MDC 后日志格式统一所有日志都能自动带上 traceId。只需在请求入口设置一次 traceId后续所有日志都自动带上。 六、日志框架配置 traceId以 logback 为例
1. logback-spring.xml 配置
!-- src/main/resources/logback-spring.xml --
configurationappender nameSTDOUT classch.qos.logback.core.ConsoleAppenderencoder!-- %X{traceId} 就是 MDC 里的 traceId --pattern[%X{traceId}] %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{36} - %msg%n/pattern/encoder/appenderroot levelINFOappender-ref refSTDOUT//root
/configuration2. 日志输出效果
[1234567890123456] 2024-06-11 10:00:00.123 INFO com.example.demo.controller.HelloController - 业务处理逻辑七、效果演示
前端所有 axios 请求自动带 traceId后端所有日志自动带 traceId全链路追踪定位问题极其方便
前端控制台示例
[traceId1234567890123456] GET /api/hello后端日志示例
[1234567890123456] 2024-06-11 10:00:00.123 INFO com.example.demo.controller.HelloController - 业务处理逻辑八、常见问题与建议
traceId 长度建议 12~20 位太短有碰撞风险太长不便于人工输入。唯一性nanoid 生成的 ID 唯一性很高足够绝大多数场景。全链路传递如果有多级服务如微服务traceId 要在各服务间传递和打印。日志格式统一建议所有日志都加上 traceId方便检索。前端异常处理可在 axios 响应拦截器中统一处理 traceId 相关异常日志。后端异常处理建议全局异常处理器也带上 traceId方便排查。MDC 清理一定要在请求结束后清理 MDC防止线程复用导致 traceId 串日志。 九、流程图
┌──────────────┐
│ 用户操作 │
└──────┬───────┘│▼
┌──────────────┐
│ 前端 axios │
│ 拦截器生成 │
│ 纯数字traceId│
└──────┬───────┘│▼
┌──────────────┐
│ 发送请求 │
│ traceId放header│
└──────┬───────┘│▼
┌──────────────┐
│ 后端拦截器 │
│ 获取/生成 │
│ traceId │
│ 放入MDC │
└──────┬───────┘│▼
┌──────────────┐
│ 日志系统 │
│ 自动带traceId│
└──────────────┘十、总结
前端用 axios 拦截器自动生成并添加 traceId后端用 Spring Boot 拦截器统一处理 traceId日志集成 MDC所有日志自动带 traceId代码更优雅日志更统一排查问题更高效