MDC(Mapped Diagnostic Context,映射调试上下文)是 log4j、 logback及 log4j2提供的一种方便在多线程条件下记录日志的功能,基于ThreadLocal实现的一种工具类。
1、新增拦截器,统一处理trace问题(Constant.TRACE_ID = "traceId")
先看MDC是否存在 traceId,有则不作处理,没有时再看header里是否有 traceId,没有的话则新生成并放置在MDC中,能解决接口请求,第三方调用,异步方法执行等场景,但线程存在丢失的情况
- @Component
- public class TraceIdInterceptor implements HandlerInterceptor {
-
- /**
- * 确保MDC有traceId
- * @param request
- * @param response
- * @param handler
- * @return
- * @throws Exception
- */
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- //如果有上层调用就用上层的ID
- String mdcTraceId = MDC.get(Constant.TRACE_ID);
- //MDC有traceId,直接返回
- if (StringUtils.isNotBlank(mdcTraceId)) {
- return true;
- }
- String headerTraceId = request.getHeader(Constant.TRACE_ID);
- //MDC没有traceId,从header取
- if (StringUtils.isNotBlank(headerTraceId)) {
- MDC.put(Constant.TRACE_ID, headerTraceId);
- return true;
- }
- //MDC、Header都没有则新生成
- MDC.put(Constant.TRACE_ID, TraceIdUtil.getTraceId());
- return true;
- }
-
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
- throws Exception {
- }
-
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
- throws Exception {
- //调用结束后删除
- MDC.remove(Constant.TRACE_ID);
- }
-
- }
- public class TraceIdUtil {
-
- public static String getTraceId () {
- return UUID.randomUUID().toString().replaceAll("-", "");
- }
- }
2、
- @PostMapping("/pageList")
- public Object list (@RequestBody ProductPage productPage) {
- IPage<Product> result = productService.pageList(productPage);
- final ResponsePage<Product> responsePage = new ResponsePage<>();
- BeanUtils.copyProperties(result, responsePage);
-
- //异步方法
- for (int i = 0; i < 2; i++) {
- new Asy().print(i);
- }
-
- HttpRequestUtil.doPost("http://127.0.0.1:9009/product/category/detail/1562264184600199170", MDC.get(Constant.TRACE_ID), new HashMap<>(), null);
-
- HttpHeaders headers = new HttpHeaders();
- headers.add("traceId", MDC.get(Constant.TRACE_ID));
- HttpEntity<String> requst = new HttpEntity<>(null, headers);
- RestTemplate restTemplate = new RestTemplate();
- restTemplate.postForObject("http://127.0.0.1:9009/product/category/detail/1562265011976994817", requst, Object.class);
- }
-
- @Slf4j
- @Async
- class Asy {
-
- public void print (int i) {
- try {
- Thread.sleep(1000L);
- log.info("异步 " + i);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
3、日志打印格式设置:%X{traceId}
-
"CONSOLE_LOG_PATTERN" - value="[${ServerIP}:${ServerPort}] %clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%level){blue} %clr([traceId:%X{traceId}]){yellow} %clr([%thread]){orange} %clr(%logger){cyan} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}" />
-
"CONSOLE_LOG_PATTERN_NO_COLOR" value="[${APP_NAME}:${ServerIP}:${ServerPort}] %d{yyyy-MM-dd HH:mm:ss.SSS} %level [traceId:%X{traceId}] [%thread] %logger %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}" />

//使用线程池时,traceId将会丢失