Slf4j MDC的使用场景

前言

如今,在 Java 开发中,日志的打印输出是必不可少的,Slf4j + LogBack 的组合是最通用的方式。

有了日志之后,我们就可以追踪各种线上问题。但是,在分布式系统中,各种无关日志穿行其中,导致我们可能无法直接定位整个操作流程。因此,我们可能需要对一个用户的操作流程进行归类标记,比如使用线程+时间戳,或者用户身份标识等;如此,我们可以从大量日志信息中grep出某个用户的操作流程,或者某个时间的流转记录。

因此,这就有了 Slf4j MDC 方法。

基于SLF4J MDC机制实现日志的链路追踪

问题描述

最近经常做线上问题的排查,而排查问题用得最多的方式是查看日志,但是在现有系统中,各种无关日志穿行其中,导致我没办法快速的找出用户在一次请求中所有的日志。

问题分析

我们没办法快速定位用户在一次请求中对应的所有日志,或者说是定位某个用户操作的所有日志,那是因为我们在输出的日志的时候没把请求的唯一标示或者说是用户身份标示输出到我们的日志中,导致我们没办法根据一个请求或者用户身份标示来做日志的过滤。所以我们在记录日志的是后把请求的唯一标示(sessionId)或者身份标示(userId) 记录到日志中这个问题就可以得到很好的解决了。

解决方案

  1. 在每次请求的时候,获取到请求的sessionId(或者自己生成一个伪sessionId),并在每次输出log的时候将这个sessionId输出到日志中。这个方式实现简单,代码侵入型强,每次输出都会多输出一个sessionId参数,工作量大,但是可控粒度高。

  2. 我们使用Logback的MDC机制,日志模板中加入sessionId格式。在日志输出格式中指定输出sessionId。

具体链接:https://www.jianshu.com/p/3dca4aeb6edd

public class LogTest {
    private static final Logger logger = LoggerFactory.getLogger(LogTest.class);

    public static void main(String[] args) {
        MDC.put("THREAD_ID", String.valueOf(Thread.currentThread().getId()));
        logger.info("纯字符串信息的info级别日志");
    }
}




    
    
        true
    
    
        
            
            [%d{yyyy-MM-dd HH:mm:ss} %highlight(%-5p) %logger.%M\(%F:%L\)] %X{THREAD_ID} %msg%n
        
    
    
        
    

因为日志级别分别有error,warn,info,debug,fatal5种,有些是5个字母的,有些是4个字母的,如果直接写%p就会对不齐,%-5p的意思是日志级别输出左对齐,右边以空格填充,%5p的意思是日志级别输出右对齐,左边以空格填充,附三张图对比

1、直接%p

Slf4j MDC的使用场景_第1张图片

2、%-5p

Slf4j MDC的使用场景_第2张图片

3、%5p

Slf4j MDC的使用场景_第3张图片

 

[2015-04-30 15:34:35 INFO  io.github.ketao1989.log4j.LogTest.main(LogTest.java:29)] 1 纯字符串信息的info级别日志

你可能感兴趣的:(sl4j)