文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java Web中日志跟踪的简单实现

2024-12-01 16:06

关注

二、MDC介绍

MDC(Mapped Diagnostic Context,映射调试上下文)是 log4j 、logback及log4j2 提供的一种方便在多线程条件下记录日志的功能。MDC 可以看成是一个与当前线程绑定的哈希表,MDC 中包含的内容可以被同一线程中执行的代码所访问。

MDC中的键值对是可以直接被日志框架所使用(即“打印”)的,只需要配置相应日志pattern。例如pattern如下:

%d{HH:mm:ss.SSS} [%thread] [%X{TraceId}] %-5level %logger{50} - %msg%n

代码如下:

public class MDCTest {

private static final Logger log = LoggerFactory.getLogger(MDCTest.class);

@Test
void test() {
MDC.put("TraceId", "123456789");
log.info("hello {}", "world");
}
}

此时控制台将输出:

21:16:04.342 [main] [123456789] INFO  com.nk.MDCTest - hello world

三、实现方案

1、基本思路

修改日志pattern,并在业务开始的时候将trace id放入到MDC,在业务结束时去除MDC的trace id。这样的好处便是代码简洁,不需要手动写trace id,日志风格也能保持统一。

业务开始的时机一般是应用收到HTTP请求,所以可以用Filter或SpringMVC的Interceptor来对MDC中trace id进行初始化和清除。在Dubbo调用的时候也可以通过类似功能的Filter来对MDC中trace id进行操作,从而达到trace id传递的作用。

2、实现(以SpringBoot为例)

2.1 修改log pattern

在SpringBoot中,直接修改application.properties即可:

logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{TraceId}] %-5level %logger{50} - %msg%n

重点在于%X{TraceId},其中TraceId需要作为key出现在MDC里。

2.1.1 业务开始

TraceId工具类,封装MDC关于trace id的基础操作:

public final class TraceIdUtil {

private static final String TRACE_ID_KEY = "TraceId";

private TraceIdUtil() {
}

public static void putIfAbsent() {
if (StrUtil.isBlank(get())) {
put(UUID.randomUUID().toString());
}
}

public static void remove() {
if (get() != null) {
MDC.remove(TRACE_ID_KEY);
}
}

public static String get() {
return MDC.get(TRACE_ID_KEY);
}

public static void put(String traceId) {
MDC.put(TRACE_ID_KEY, traceId);
}
}

Filter方式和Interceptor二选其一既可,其基本思想是一样的。

Filter方式

@Component
public class LogFilter implements Filter {

@Override
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
TraceIdUtil.putIfAbsent();//生成trace id放入MDC中
try {
filterChain.doFilter(servletRequest, servletResponse);
} finally {
TraceIdUtil.remove();//移除MDC中的trace id
}
}
}

Interceptor

@Configuration
public class LogInterceptor implements WebMvcConfigurer {

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AsyncHandlerInterceptor() {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
TraceIdUtil.putIfAbsent();//生成trace id放入MDC中
return AsyncHandlerInterceptor.super.preHandle(request, response, handler);
}

@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler, Exception ex) throws Exception {
TraceIdUtil.remove();//移除MDC中的trace id
AsyncHandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
});
WebMvcConfigurer.super.addInterceptors(registry);
}
}

2.1.2 业务中使用

正常使用logger,无需关心trace id。例如:

@RestController
@RequestMapping("/api/user")
@Slf4j
public class UserController {

@Autowired
private UserService userService;

@GetMapping("/{userId}")
public UserDto queryUser(@PathVariable Long userId) {
log.info("query user by id:{}", userId);
UserDto user = userService.query(userId);
log.info("query user result:{}", user);
return user;
}
}

请求该接口将输出如下的日志样式:

2022-04-05 09:40:17.638 [http-nio-8080-exec-1] [a02b13d81c224e49956afd4efbb85ca8] INFO  com.nk.webapp.controller.UserController - ready to query user by id:1
2022-04-05 09:40:17.670 [http-nio-8080-exec-1] [a02b13d81c224e49956afd4efbb85ca8] INFO com.nk.webapp.controller.UserController - query result:UserDto(userId=1, username=zhang3, age=23, email=abc@example.com)

四、总结

日志链路的跟踪核心是使用MDC作为trace id载体,在业务开始阶段一般通过拦截器就生成trace id并放入到MDC中,并根据MDC的相关特性将trace id投射到日志文本中,从而实现在同一个业务调用链路中的日志具有唯一标识。

来源:GreatSQL社区内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯