MDC日志追踪
作者:互联网
日志追踪
1.如何实现 问题 以及解决方案
初级 每层传参下去 从controller -> service -> dao
中级 通过threalocal
什么是threadlocal 为线程创建一个副本 是以线程号为id 的map 可以塞值 塞我们想要的 traceId
框架MDC
MDC(Mapped Diagnostic Context,映射调试上下文)是 log4j 和 logback 提供的一种方便在多线程条件下记录日志的功能。
MDC中的put方法其实就是讲键值对放入一个Hashtable对象中,然后赋值给当前线程的ThreadLocal.ThreadLocalMap对象,即threadLocals,这保证了各个线程的在MDC键值对的独立性。
边界
1.mdc争对的是当前线程 ,所以当你使用异步,或者说new Thread的时候就不支持了
如何解决: 可以在多线程里面从新设置一遍 MDC.put(“traceId”,“业务唯一键”)
2.分布式的时候 当A系统 调用B系统的时候 下游的系统如何获取traceId
如何解决 从A系统到B系统 走的是hettp 协议 所以我们就可以在url上面做文章
hettp://www.bai.A?traceId=唯一键
springcloud里面的sleuth 就是通过这个方法去实现的
我们直接的服务 怎么去实现他呢 编写两个filter 去实现他
转发的时候对url里面设置一个这个的请求参数
消费端那边先去获取这个traceId 再通过mdc put进去 日志打印的格式加上traceID 这个参数
3.日志采集 服务很多 不知你哪一台去获取 elk 后续再涉及
代码实现
pom文件
<!--一定要先把这里面的logging给排除掉-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
application.properties
#指定log的配置文件
logging.config=classpath:log4j2.xml
log4j2.xml
%X{name}会查询设置到MDC中的变量 这个非常重要
%d{yyyy-MM-dd HH:mm:ss,SSS} %t %X{traceId} %-5p %c{1}:%L -%m%n
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!-- status log4j2内部日志级别 -->
<configuration status="INFO">
<!-- 全局参数 %X{name}会查询设置到MDC中的变量 -->
<Properties>
<Property name="pattern">%d{yyyy-MM-dd HH:mm:ss,SSS} %t %X{traceId} %-5p %c{1}:%L -%m%n</Property>
<Property name="displayName">EurekaServer</Property>
</Properties>
<Appenders>
<Console name="console" target="SYSTEM_OUT" follow="true">
<PatternLayout>
<pattern>${pattern}</pattern>
</PatternLayout>
</Console>
<!-- 文件 每次运行程序会自动清空,由append属性决定 -->
<File name="error" fileName="${displayName}_error.log" append="false">
<!-- 指定error 级别的日志 -->
<ThresholdFilter level="ERROR" onMatch="ACCEPT"
onMismatch="DENY" />
<PatternLayout>
<pattern>${pattern}</pattern>
</PatternLayout>
</File>
<!-- 滚动文件 -->
<RollingFile name="rollingFile" fileName="${displayName}.log"
filePattern="${displayName}_%d{yyyy-MM-dd}.log">
<PatternLayout>
<pattern>${pattern}</pattern>
</PatternLayout>
<!-- 按大小划分 -->
<SizeBasedTriggeringPolicy size="50 MB" />
</RollingFile>
</Appenders>
<Loggers>
<!-- <Logger name="org.apache.catalina.util.LifecycleBase" level="ERROR"
/> <Logger nabaime="org.apache.coyote.http11.Http11NioProtocol" level="WARN"
/> <Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="WARN"
/> -->
<Logger name="org.springframework" level="WARN" />
<Logger name="com.bai" level="DEBUG" />
<Root level="DEBUG">
<AppenderRef ref="console"></AppenderRef>
<AppenderRef ref="error"></AppenderRef>
<AppenderRef ref="rollingFile"></AppenderRef>
</Root>
</Loggers>
</configuration>
编写任意一个拦截器
import org.slf4j.MDC;
/**
* @Author BAI
* @Description 语言转化拦截器
*/
@Slf4j
public class MyLocaleChangeInterceptor implements HandlerInterceptor {
public static final String TRACE_ID ="traceId";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException {
// 使用mdc塞值 添加日志追踪
String traceId = UUID.randomUUID().toString().replace("-","");
MDC.put(TRACE_ID, traceId);
// 这个添加的操作一定要在preHandle 一般误区会以为会在postHandle
// 但是使用的时候会发现 在使用postHandle 之前 已经返回给前端
response.addHeader(TRACE_ID,traceId);
I18nLocalResolver i18NLocalResolver = new I18nLocalResolver();
Locale locale = i18NLocalResolver.resolveLocale(request);
i18NLocalResolver.setLocale(request,response,locale);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("afterCompletion start...");
MDC.remove(TRACE_ID);
log.info("afterCompletion end...");
}
}
线程池或者异步任务简单处理
String traceId = MDC.get("traceId");
for (int i = 0; i < 1000; i++) {
newFixedThreadPool(1000).execute(()->{
MDC.put("traceId",traceId);
log.info("stu:",stu.getOperateEnum());
MDC.remove("traceId");
});
}
标签:traceId,MDC,boot,线程,put,日志,追踪 来源: https://blog.csdn.net/weixin_42899433/article/details/113764306