spring 项目实现带请求链路id的日志记录
我们在做java项目的时候通常需要通过请求日志来排查定位线上问题,在日志比较多而我们又需要查找整个请求的全部日志的时候会比较困难。所以,就需要在日志记录的时候讲同一个请求的关键日志用同一个唯一标识串联起来。这样查找的时候就会比较好查找。下面来用java aop实现请求id的日志记录。(该支持子线程继承主线程请求id)
一:首先我们需要一个日志请求链路id切面类
注意:如果不考虑多线程则(第二步和第三步可以不要)
package com.iMagine.iMagine_pro.aop;
import com.iMagine.iMagine_common.utils.UUIDUtil;
import com.iMagine.iMagine_pro.utils.TokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
/**
* @author 名一
* @ClassName TraceIdAspect
* @description: 日志请求链路id切面处理
* @datetime 2024年 12月 16日 14:28
* @version: 1.0
*/
@Slf4j
@Aspect
@Component
public class TraceIdAspect {
/** 链路追踪id */
public final static String TRACE_ID = "TRACE_ID";
/** 用户 */
public final static String USER = "USER";
/**
* 链路id切点定义
*/
@Pointcut("execution(* com.iMagine.iMagine_pro.controller.*.*(..))")
public void TraceIdCut() {
}
/**
* 链路id添加
*/
@Before("TraceIdCut()")
public void cutProcessBefore() {
MDC.put(TRACE_ID, UUIDUtil.getUUID());
//以下代码为记录用户信息,方便更直观的识别日志操作人信息。若不需要可以将下面部分删除
String nickname = TokenUtil.getNicknameByToken();
if (null == nickname){
nickname = "游客访问";
}
MDC.put(USER, nickname);
}
/**
* 链路id清除
*/
@After("TraceIdCut()")
public void cutProcessAfter() {
MDC.clear();
}
}
package com.iMagine.iMagine_common.utils; import java.util.UUID; /**
* @author 名一
* @ClassName UUIDUtil
* @description: UUID工具类
* @datetime 2024年 04月 23日 11:49
* @version: 1.0
*/
public class UUIDUtil { /**
* 获取UUID
*
* @return
*/
public static String getUUID() {
//生产uuid并去掉uuid的短横线
return UUID.randomUUID().toString().replace("-", "");
}
}
二:创建一个处理多线程链路追踪的工具类
package com.iMagine.iMagine_common.utils;
import com.iMagine.iMagine_common.constant.SysConstant;
import org.slf4j.MDC;
import java.util.Map;
/**
* @author 名一
* @ClassName ThreadMdcUtil
* @description: 多线程链路追踪工具类
* @datetime 2024年 12月 16日 14:57
* @version: 1.0
*/
public class ThreadMdcUtil {
// 获取唯一性标识
public static String generateTraceId() {
return UUIDUtil.getUUID();
}
public static void setTraceIdIfAbsent() {
if (MDC.get(SysConstant.TRACE_ID) == null) {
MDC.put(SysConstant.TRACE_ID, generateTraceId());
}
}
/**
* 用于父线程向线程池中提交任务时,将自身MDC中的数据复制给子线程
*
* @param runnable 要执行的线程
* @param context 父线程的mdc
* @return 链路id传递后的任务
*/
public static Runnable wrap(final Runnable runnable, final Map<String, String> context) {
return () -> {
if (context == null) {
MDC.clear();
} else {
MDC.setContextMap(context);
}
setTraceIdIfAbsent();
try {
runnable.run();
} finally {
MDC.clear();
}
};
}
}
三:在往线程池放任务的时候做请求链路id传递
/**
* 线程池添加 [ai server 相关操作(psot)]任务
*
* @param task 添加的任务
*/
public static void addSendPostThreadToThreadPool(SendPostThread task) {
log.info("addSendPostThreadToThreadPool pool:{}, task:{}", pool, task);
try {
pool.execute(ThreadMdcUtil.wrap(task, MDC.getCopyOfContextMap()));
} catch (Exception e) {
log.error("addSendPostThreadToThreadPool error pool:{}, task:{}, e:", pool, task, e);
}
}
四:在日志配置里将链路追踪id加入日志输出格式的配置里
<!-- 日志输出格式 (其中%X{TRACE_ID}是mdc里边链路请求id的key,user-%X{USER}是用户信息的key)-->
<property name="ENCODER_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %X{TRACE_ID} user-%X{USER} %-5level %logger{32}-[%line] - %msg%n"/>
到此spring 项目实现带请求链路id的日志记录就完成了
spring 项目实现带请求链路id的日志记录的更多相关文章
- 9.Spring Boot实战之配置使用Logback进行日志记录
转自:https://blog.csdn.net/meiliangdeng1990/article/details/54300227 Spring Boot实战之配置使用Logback进行日志记录 在 ...
- 通过 Spring RestTemplate 调用带请求体的 Delete 方法(Delete With Request Body)
Spring 框架的RestTemplate 类定义了一些我们在通过 java 代码调用 Rest 服务时经常需要用到的方法,使得我们通过 java 调用 rest 服务时更加方便.简单.但是 Res ...
- Spring AOP的日志记录
现在的项目是Spring+MyBatis,前段时间项目经理让我干了一个活,就是给所有的controller里的所有方法加上日志记录的代码,其实没有多少,也就300来个方法,也没有抱怨什么,一边打着瞌睡 ...
- Spring Boot 之日志记录
Spring Boot 之日志记录 Spring Boot 支持集成 Java 世界主流的日志库. 如果对于 Java 日志库不熟悉,可以参考:细说 Java 主流日志工具库 关键词: log4j, ...
- Spring MVC中forward请求转发2种方式(带参数)
Spring MVC中forward请求转发2种方式(带参数) http://www.51gjie.com/javaweb/956.html
- Spring项目集成ShiroFilter简单实现权限管理
Shiros是我们开发中常用的用来实现权限控制的一种工具包,它主要有认证.授权.加密.会话管理.与Web集成.缓存等功能.我是从事javaweb工作的,我就经常遇到需要实现权限控制的项目,之前我们都是 ...
- Spring Cloud 系列之 Sleuth 链路追踪(一)
随着微服务架构的流行,服务按照不同的维度进行拆分,一次请求往往需要涉及到多个服务.互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发.可能使用不同的编程语言来实现.有可能布在了 ...
- go-zero 是如何追踪你的请求链路的
go-zero 是如何追踪你的请求链路 微服务架构中,调用链可能很漫长,从 http 到 rpc ,又从 rpc 到 http .而开发者想了解每个环节的调用情况及性能,最佳方案就是 全链路跟踪. 追 ...
- spring boot / cloud (十六) 分布式ID生成服务
spring boot / cloud (十六) 分布式ID生成服务 在几乎所有的分布式系统或者采用了分库/分表设计的系统中,几乎都会需要生成数据的唯一标识ID的需求, 常规做法,是使用数据库中的自动 ...
- Spring项目集成ShiroFilter简单配置
Shiros是我们开发中常用的用来实现权限控制的一种工具包,它主要有认证.授权.加密.会话管理.与Web集成.缓存等功能.我是从事javaweb工作的,我就经常遇到需要实现权限控制的项目,之前我们都是 ...
随机推荐
- [29] CSP模拟2
A.不相邻集合 考虑值域上连续的段,可以发现连续的长度为 \(x\) 的段的贡献必定为 \(\lceil{\frac{x}{2}}\rceil\) 考虑并查集维护值域连续的段的大小,每次询问求出全部连 ...
- 《MySQL 5.7从入门到精通(视频教学版)》代码课件教学视频下载
<MySQL 5.7从入门到精通(视频教学版)>代码课件教学视频下载 https://pan.baidu.com/s/1ZufDV6a_PEnjp-Bdh4IkuQ 提取码:vgnr 无版 ...
- [kubernetes]二进制方式部署单机k8s-v1.30.5
前言 之前在单机测试k8s的kind最近故障了,虚拟机运行个几分钟后就宕机了,不知道是根因是什么,而且kind部署k8s不太好做一些个性化配置,干脆用二进制方式重新搭一个单机k8s. 因为是用来开发测 ...
- PasteForm最佳CRUD实践,实际案例PasteTemplate详解之3000问(四)
无论100个表还是30个表,在使用PasteForm模式的时候,管理端的页面是一样的,大概4个页面, 利用不同操作模式下的不同dto数据模型,通过后端修改对应的dto可以做到控制前端的UI,在没有特别 ...
- 封装JWT - 生成 jwt 和解析 jwt
1. ASP.NET Core 身份验证和授权验证的功能由Authentication,Authorization中间件提供 :app.UseAuthentication(),app.UseAutho ...
- vagrant快速安装虚拟机
- feign调用其他服务解码错误
1.在使用A服务通过feign调用B服务时报错: feign.codec.DecodeException: Error while extracting response for type [clas ...
- 立即报名 | AI +Serverless Meetup 上海站 8 月 5 日等你相约!
自 2021 年 5 月后,KubeSphere 社区与上海的各位小伙伴已阔别两年,许久不见,甚是想念!2023 年 8 月 5 日,KubeSphere 社区将走进上海组织一场主题为 "A ...
- Kubernetes 集群中流量暴露的几种方案
作者:KaliArch(薛磊),某 Cloud MSP 服务商产品负责人,熟悉企业级高可用 / 高并发架构,包括混合云架构.异地灾备,熟练企业 DevOps 改造优化,熟悉 Shell/Python/ ...
- linux 基础(1)快速查询指令的用法
--help 几乎所有的指令,都可以使用--help选项进行查询.给命令使用--help选项,就会直接出现一段说明命令的文字. > date --help 用法:date [选项]... [+格 ...