MDC.put(key, value);
MDC.get(key);
%X{key}
GenericFilterBean
。1.定义一个简单的接口:
/**
*
*
* @author hanchao
*/
@RestController
public class DemoController {
private final Logger logger = Logger.getLogger(DemoController.class);
@GetMapping("/demo/by-name")
public String demo(String name) {
logger.info("name:" + name);
return name;
}
}
2.在浏览器调用接口: http://localhost:8080/demo/by-name?name=zhangsan
3.查看相关日志:
INFO pers.hanchao.trace.controller.DemoController:19 - name:zhangsan
增加TraceId操作的工具类,提供traceId的默认取值、setter、getter和生成。
/**
* traceId工具类
*
* @author hanchao
*/
public class TraceIdUtil {
private static final String TRACE_ID = "traceId";
/**
* 当traceId为空时,显示的traceId。随意。
*/
private static final String DEFAULT_TRACE_ID = "0";
/**
* 设置traceId
*/
public static void setTraceId(String traceId) {
//如果参数为空,则设置默认traceId
traceId = StringUtils.isBlank(traceId) ? DEFAULT_TRACE_ID : traceId;
//将traceId放到MDC中
MDC.put(TRACE_ID, traceId);
}
/**
* 获取traceId
*/
public static String getTraceId() {
//获取
String traceId = MDC.get(TRACE_ID);
//如果traceId为空,则返回默认值
return StringUtils.isBlank(traceId) ? DEFAULT_TRACE_ID : traceId;
}
/**
* 判断traceId为默认值
*/
public static Boolean defaultTraceId(String traceId) {
return DEFAULT_TRACE_ID.equals(traceId);
}
/**
* 生成traceId
*/
public static String genTraceId() {
return UUID.randomUUID().toString();
}
}
自定义过滤器,对全部请求进行traceId处理。这里处理有些粗暴,可自行细化。
/**
* traceId过滤器,用于设置traceId
*
* @author hanchao
*/
@WebFilter(urlPatterns = "/*", filterName = "traceIdFilter")
@Order(1)
public class TraceIdFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//traceId初始化
initTraceId((HttpServletRequest) servletRequest);
//执行后续过滤器
filterChain.doFilter(servletRequest,servletResponse);
}
/**
* traceId初始化
*/
private void initTraceId(HttpServletRequest request) {
//尝试获取http请求中的traceId
String traceId = request.getParameter("traceId");
//如果当前traceId为空或者为默认traceId,则生成新的traceId
if (StringUtils.isBlank(traceId) || TraceIdUtil.defaultTraceId(traceId)){
traceId = TraceIdUtil.genTraceId();
}
//设置traceId
TraceIdUtil.setTraceId(traceId);
}
}
不要忘记在SpringBoot的启动类加上@ServletComponentScan
注解,否则自定义的Filter无法生效。
/**
* 使用嵌入式容器时,可以使用@ServletComponentScan启用@WebServlet,@ WebFilter和@WebListener注释类的自动注册。
*/
@ServletComponentScan(basePackages = "pers.hanchao.trace.filter")
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
修改日志的layout
格式,将MDC中的traceId打印出来:
<PatternLayout pattern="%5p %c:%L - %m %throwable{separator( --> )}%n"/>
<PatternLayout pattern="%5p traceId:%X{traceId} %c:%L - %m %throwable{separator( --> )}%n"/>
1.在浏览器多次调用接口: http://localhost:8080/demo/by-name?name=zhangsan
2.查看相关日志:
INFO traceId:5ee05f9b-432c-401f-ae24-6adaf2f31cf4 pers.hanchao.trace.controller.DemoController:19 - name:zhangsan
INFO traceId:b835352f-3a22-462c-965e-c426309ae3b8 pers.hanchao.trace.controller.DemoController:19 - name:zhangsan
INFO traceId:942d4f8f-f3c6-4688-a534-3429b6c9e92d pers.hanchao.trace.controller.DemoController:19 - name:zhangsan