MDC

MDC

简介

MDC(Mapped Diagnostic Context) 是 Log4j 日志库的一个概念或功能,可用于将相关日志消息分组在一起。

使用方式

首先需要编写一个过滤器用于拦截请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.UUID;

@Slf4j
public class MdcFilter implements Filter {

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String traceId = httpServletRequest.getHeader("traceId");
if (traceId == null) {
traceId = UUID.randomUUID().toString();
}
MDC.put("traceId", traceId);
MDC.put("ts", String.valueOf(LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli()));
log.info(httpServletRequest.getRequestURL() + " call received");
chain.doFilter(request, response);
} finally {
MDC.clear();
}
}
}

然后需要将此过滤器加载到 Spring :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Application {

@Bean
public FilterRegistrationBean<MdcFilter> loggingFilter() {
FilterRegistrationBean<MdcFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new MdcFilter());
registrationBean.addUrlPatterns("/*");
return registrationBean;
}

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

}

编写如下配置文件设置显示样式:

1
2
3
4
5
6
7
8
server:
port: 8080
spring:
application:
name: demo
Logging:
pattern:
level: '%5p [${spring.application.name:},%mdc{traceId:-},%mdc{ts:-}]'

然后需要编写一个样例的 Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequestMapping
public class DemoController {

@GetMapping("/demo")
public String hello() {
log.info("TraceId: {} - Hello World!", MDC.get("traceId"));
return "Hello World!";
}

}

访问 http://localhost:8080/demo 即可看到结果日志。

参考资料

How to distinguish logging per Client or Request in Java? Use MDC or Mapped Diagnostic Context in Log4j Example

基于MDC实现长链路跟踪


MDC
https://wangqian0306.github.io/2023/mdc/
作者
WangQian
发布于
2023年12月21日
许可协议