log4j2调用链使用

367 阅读1分钟

实现方案

  • NDC:基于堆寨,将调用链ID存入堆寨中,但是每次调用结束后需要手动清理
  • MDC:基于MAP,调用链ID放入MAP中,优点调用结束后不需要手动清理
  • 扩展类PatternLayout,重写finalizeConverter方法

实现

对比之后选择通过MDC方式来实现:

  1. 通过spring拦截器,拦截所有请求,将自定义生成的调用链ID存入到MDC中,同时放入到线程中,后面调用别的服务的时候可以从线程中获取到,形成完整的调用链
  2. 设置log4j2配置文件打印格式内容为%X{调用链ID}。
<Property name="LOG_PATTERN_HEAD">%d{yyyy-MM-dd HH:mm:ss.SSS}$$[${hostName}]$$%p$$[${serviceName}]$$%t$$%M$$%c$$%X{调用链ID}$$</Property>
@Component
@Log4j2
public class AtomicInterceptor extends HandlerInterceptorAdapter {

    private boolean setConsoleContext(HttpServletRequest request) {
        try {
            ConsoleContext context = new ConsoleContext();
            context.setRequest(request);
            context.setBeginMs(System.currentTimeMillis());
            // 创建调用链ID的公共方法
            traceID = TraceUtil.newTraceId();
            context.setTraceId(traceID);
            MDC.put("traceID", traceID);
            if(StringUtils.isNotBlank(traceMD5)){
                context.setTraceMD5(traceMD5);
                MDC.put("traceMD5", traceMD5);
            }
            // 放入线程中,方便后面调用别的服务获取传入到别的方服务,形成完整的调用链
            ThreadLocalManager.setConsoleContext(context);
        } catch (Exception e) {
            log.error("error in preHandle getUser. url is:"+request.getRequestURL(), e);
            return false;
        }
        return true;
    }