##什么是MDC(Mapped Diagnostic Contexts)
MDC本质上是一个Map,基于线程用于存储任意键值对,通常是调用的上下文(context)信息,
由应用代码存储键值对,并由日志框架应用到日志消息中。如系统接收到请求时,
系统会把请求ID,请求发起方ID,请求发起方IP地址和请求参数放在MDC。
目前支持MDC的日志框架包括log4j和logback。
MDC是线程独立、线程安全的,通常无论是HTTP还是RPC请求,都是在各自独立的线程中完成的.
MDC能为我们做什么
大部分我们的程序调用情况都比较复杂,所以在很多地方都会打印方法的入参及出参日志。
但当请求一多的时候我们无法区分,哪条日志是同一次请求的。
MDC这时候出场,它可以 把一次请求中所有请求日志都找出来。
logback.xml如何使用MDC
<property name="LOG_PATTERN" value="[timestamp=%d{yyyy-MM-dd HH:mm:ss.SSS}]
[level=%p] [tx_id=%X{traceId}] [app_id=${applicationName}] [%t][%L][%c.%M] %m%n"/>
%X{traceId}就是在引用MDC中的内容,{key}可以自己通过代码设置。
其他地方使用也大致可以理解成两步:
1:定义日志的格式,其中%X{}代表去MDC取值
2:通过aop或者拦截器等方式在初始入口设置MDC的值
Springboot-用MDC生成链路追踪Txid
定义TraceIdUtil的常量
public class TraceIdUtil {
public static final String TRACE_ID = "traceId";
/**
* 可以根据自己的需求生成不同个是tx_id
*
* @return
*/
public static String getTxID() {
return UUID.randomUUID().toString().replace("-", "");
}
public static void setTraceId(String traceId) {
if (StringUtils.isNoneBlank(traceId)) {
MDC.put(TRACE_ID, traceId);
}
}
public static void clearTraceId() {
MDC.clear();
}
}
Filter拦截
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.AbstractRequestLoggingFilter;
import traceid.request.logging.utill.TraceIdUtil;
import javax.servlet.http.HttpServletRequest;
/**
* Created by on 2021/12/24.
*/
@Component
public class TraceIdFilter extends AbstractRequestLoggingFilter {
/**
* 方法前拦截
*
* @param httpServletRequest
* @param s
*/
@Override
protected void beforeRequest(HttpServletRequest httpServletRequest, String s) {
//如果在请求的源头找不到,就生成一个放到header
String txId = httpServletRequest.getHeader(TraceIdUtil.TRACE_ID);
if (StringUtils.isEmpty(txId)) {
TraceIdUtil.setTraceId(TraceIdUtil.getTxID());
} else {
TraceIdUtil.setTraceId(txId);
}
}
@Override
protected void afterRequest(HttpServletRequest httpServletRequest, String s) {
TraceIdUtil.clearTraceId();
}
}
测试类构造
@RestController
public class TestController {
private Logger logger = LoggerFactory.getLogger(getClass());
@RequestMapping(value = "/test")
public String test(String name) {
logger.info("get test,time={},name={}", System.currentTimeMillis(), name);
testLog();
return "success";
}
private void testLog() {
logger.info("testlog");
}
}
最终效果
作者:javanull
链接:Springboot-用MDC生成链路追踪Txid - 掘金