Spring Boot、MDC、自定义注解实现链路调用日志追踪,简单日志链路追踪实现
Spring Boot、MDC、自定义注解实现链路调用日志追踪,简单链路追踪实现
关于MDC
MDC(Mapped Diagnostic Context)是一个用于日志记录的功能,它允许开发者在日志信息中添加上下文信息,以便更好地追踪和调试应用程序的运行状态。MDC通常与SLF4J(Simple Logging Facade for Java)和Logback等日志框架一起使用。内部多个实现类,使用 ThreadLocal 实现数据上下文隔离
配置 spring 日志格式
复制
# 加了点日志的颜色格式,可以去掉
logging:
pattern:
console: %yellow(%date{yyyy-MM-dd HH:mm:ss}) | %highlight(%-5level)| [%red(%thread)] | %green(%logger:%line) | [%blue(%X{traceId})] | %cyan(%msg%n)
和过滤器一起使用,实现简单日志链路追踪
复制
import cn.hutool.core.util.StrUtil;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.slf4j.MDC;
import java.io.IOException;
import java.util.UUID;
@Slf4j
public class LogFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, @NotNull FilterChain chain) throws IOException, ServletException {
try {
HttpServletRequest httpRequest = (HttpServletRequest) request;
// 这里可以读取其他服务的调用(调用方以及后续调用方把 traceId 放在请求头),实现多个服务间的日志链路追踪
String traceId = httpRequest.getHeader("traceId");
if (StrUtil.isBlank(traceId)) {
traceId = UUID.randomUUID().toString();
}
MDC.put("traceId", traceId);
chain.doFilter(request, response);
} finally {
MDC.clear();
}
}
}
配合注解使用
注解
复制
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogTrace {
}
注解处理器
复制
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.UUID;
@Aspect
@Component
public class LogTraceAspect {
@Around("@annotation(LogTrace)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// 这里可以读取其他服务的调用(调用方以及后续调用方把 traceId 放在请求头),实现多个服务间的日志链路追踪
String traceId = request.getHeader("traceId");
if (StrUtil.isEmpty(traceId)) {
traceId = UUID.randomUUID().toString();
}
try {
MDC.put("traceId", traceId);
return joinPoint.proceed();
} finally {
MDC.clear();
}
}
}
最终效果

Preview
作者:https://blog.xn--rpv331d.com/望舒
链接:https://blog.xn--rpv331d.com/望舒/blog/45
转载注意保留文章出处...
0
0
0
100
No data