lf4j中的MDC

slf4j中MDC是什麼鬼

  slf4j除了trace、debug、info、warn、error這幾個日誌接口外,還可以配合MDC將數據寫入日誌。換句話說MDC也是用來記錄日誌的,但它的使用方式與使用日誌接口不同。

  在使用日誌接口時我們一般這麼做

1

2

3

4

Logger LOG = LoggerFactory.getLogger("LOGNAME_OR_CLASS");

if(LOG.isDebugEnabled()) {

  LOG.debug("log debug");

}

  MDC從使用方式上有些不同,我對它的理解是MDC可以將一個處理線程中你想體現在日誌文件中的數據統一管理起來,根據你的日誌文件配置決定是否輸出。

  比如以下但不限於以下場景可以考慮使用MDC來達到目的

  1. 我們想在日誌中體現請求用戶IP地址
  2. 用戶使用http客戶端的user-agent
  3. 記錄一次處理線程的日誌跟蹤編號(這個編號目的是爲了查詢日誌方便,結合grep命令能根據跟蹤編號將本次的處理日誌全部輸出)

MDC的使用

  org.slf4j.MDC我個人會用AOP或Filter或Interceptor這類工具配合使用,獲得你希望輸出到日誌的變量並調用MDC.put(String key, String val),比如下面代碼片段第5行:

1

2

3

4

5

6

7

8

9

10

11

12

13

@Around(value = "execution(* com.xx.xx.facade.impl.*.*(..))", argNames="pjp")

  public Object validator(ProceedingJoinPoint pjp) throws Throwable {

      try {

          String traceId = TraceUtils.begin();

          MDC.put("mdc_trace_id", traceId);

          Object obj = pjp.proceed(args);

          return obj;

      catch(Throwable e) {

          //TODO 處理錯誤

      finally {

          TraceUtils.endTrace();

      }

  }   

   代碼通過AOP記錄了每次請求的traceId並使用變量"mdc_trace_id"記錄,在日誌配置文件裏需要設置變量才能將"mdc_trace_id"輸出到日誌文件中。我以logback配置文件爲例,看日誌第10行%X{mdc_trace_id}:

1

2

3

4

5

6

7

8

9

10

11

12

<appender name="ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">

      <file>${CATALINA_BASE}/logs/all.log</file>

      <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

          <!-- daily rollover -->

          <fileNamePattern>${CATALINA_BASE}/logs/all.%d{yyyy-MM-dd}.log</fileNamePattern>

          <!-- keep 30 days' worth of history -->

          <maxHistory>30</maxHistory>

      </rollingPolicy>

      <encoder charset="UTF-8">

          <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - traceId:[%X{mdc_trace_id}] - %msg%n</pattern>

      </encoder>

  </appender>

MDC帶來的好處

  1. 如果你的系統已經上線,突然有一天老闆說我們增加一些用戶數據到日誌裏分析一下。如果沒有MDC我猜此時此刻你應該處於雪崩狀態。MDC恰到好處的讓你能夠實現在日誌上突如其來的一些需求
  2. 如果你是個代碼潔癖,封裝了公司LOG的操作,並且將處理線程跟蹤日誌號也封裝了進去,但只有使用了你封裝日誌工具的部分才能打印跟蹤日誌號,其他部分(比如hibernate、mybatis、httpclient等等)日誌都不會體現跟蹤號。當然我們可以通過linux命令來繞過這些困擾。
  3. 使代碼簡潔、日誌風格統一

分類: Log

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章