为什么使用MDC进行记录日志信息

一、MDC的优点
1.如果你的系统已经上线,突然有一天老板说我们增加一些用户数据到日志里分析一下,如果没有MDC我猜此时此刻你应该处于雪崩状态,MDC恰到好处的让你能够实现在日志上突如其来的一些需求。
2.如果你是个代码洁癖,封装了公司LOG的操作,并且将处理线程跟踪日志号也封装了进去,但只有使用了你封装日志工具的部分才能打印跟踪日志号,其他部分(比如hibernate、mybatis、httpclient等等)日志都不会体现跟踪号。当然我们可以通过linux命令来绕过这些困扰。
3.使代码简洁、日志风格统一。
二、进行看一看源码

package org.slf4j;

import java.util.Map;
import org.slf4j.helpers.NOPMDCAdapter;
import org.slf4j.helpers.Util;
import org.slf4j.impl.StaticMDCBinder;
import org.slf4j.spi.MDCAdapter;

public class MDC
{
  static final String NULL_MDCA_URL = "http://www.slf4j.org/codes.html#null_MDCA";
  static final String NO_STATIC_MDC_BINDER_URL = "http://www.slf4j.org/codes.html#no_static_mdc_binder";
  static MDCAdapter mdcAdapter;

  static
  {
    try
    {
      mdcAdapter = StaticMDCBinder.SINGLETON.getMDCA();
    }
    catch (NoClassDefFoundError ncde)
    {
      mdcAdapter = new NOPMDCAdapter();
      String msg = ncde.getMessage();
      if ((msg != null) && (msg.indexOf("StaticMDCBinder") != -1))
      {
        Util.report("Failed to load class \"org.slf4j.impl.StaticMDCBinder\".");
        Util.report("Defaulting to no-operation MDCAdapter implementation.");
        Util.report("See http://www.slf4j.org/codes.html#no_static_mdc_binder for further details.");
      }
      else
      {
        throw ncde;
      }
    }
    catch (Exception e)
    {
      Util.report("MDC binding unsuccessful.", e);
    }
  }

  public static void put(String key, String val)
    throws IllegalArgumentException
  {
    if (key == null) {
      throw new IllegalArgumentException("key parameter cannot be null");
    }
    if (mdcAdapter == null) {
      throw new IllegalStateException("MDCAdapter cannot be null. See also http://www.slf4j.org/codes.html#null_MDCA");
    }
    mdcAdapter.put(key, val);
  }

  public static String get(String key)
    throws IllegalArgumentException
  {
    if (key == null) {
      throw new IllegalArgumentException("key parameter cannot be null");
    }
    if (mdcAdapter == null) {
      throw new IllegalStateException("MDCAdapter cannot be null. See also http://www.slf4j.org/codes.html#null_MDCA");
    }
    return mdcAdapter.get(key);
  }

  public static void remove(String key)
    throws IllegalArgumentException
  {
    if (key == null) {
      throw new IllegalArgumentException("key parameter cannot be null");
    }
    if (mdcAdapter == null) {
      throw new IllegalStateException("MDCAdapter cannot be null. See also http://www.slf4j.org/codes.html#null_MDCA");
    }
    mdcAdapter.remove(key);
  }

  public static void clear()
  {
    if (mdcAdapter == null) {
      throw new IllegalStateException("MDCAdapter cannot be null. See also http://www.slf4j.org/codes.html#null_MDCA");
    }
    mdcAdapter.clear();
  }

  public static Map<String, String> getCopyOfContextMap()
  {
    if (mdcAdapter == null) {
      throw new IllegalStateException("MDCAdapter cannot be null. See also http://www.slf4j.org/codes.html#null_MDCA");
    }
    return mdcAdapter.getCopyOfContextMap();
  }

  public static void setContextMap(Map<String, String> contextMap)
  {
    if (mdcAdapter == null) {
      throw new IllegalStateException("MDCAdapter cannot be null. See also http://www.slf4j.org/codes.html#null_MDCA");
    }
    mdcAdapter.setContextMap(contextMap);
  }

  public static MDCAdapter getMDCAdapter()
  {
    return mdcAdapter;
  }
}

三、使用MDC将日志信息存入日志文件中
1.首先导入maven的jar包

  <dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
  </dependency>
  <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.21</version>
  </dependency> 

2.编辑简单的demo

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

public class TestLog {
    private static final Logger logger = LoggerFactory.getLogger(TestLog.class);
    public static void main(String[] args) {
        MDC.put("TESE_ID", String.valueOf(Thread.currentThread().getId()));
        logger.info("测试日志中是否有当前自定义log");
    }
}

3.配置自定义日志文件与格式logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
    <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 自定义存入日志文件的格式 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level [%logger{16}] [%X{REQID}] [%X{SID}] [%X{UID}] %msg%n</pattern>
        </encoder>
    </appender>
    <!-- 通过MDC.put()方法进行将打印的用户详细的操作信息放入日志文件中,可以很好的进行分析日志 -->
    <appender name="FILE"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>/logs/logs.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- daily rollover -->
            <!-- 日志存入的地点 -->
            <fileNamePattern>/logs/logs.%d{yyyy-MM-dd}.log 
            </fileNamePattern>
            <!--   每6天清理一次日志文件 -->
            <!-- keep 30 days' worth of history -->
            <maxHistory>6</maxHistory>
        </rollingPolicy>

        <append>true</append>
        <encoder>
             <!-- 自定义存入日志文件的格式 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level [%logger{16}] [%X{REQID}] [%X{SID}] [%X{UID}] %msg%n</pattern>
        </encoder>
    </appender>
</configuration>

猜你喜欢

转载自blog.csdn.net/qq_32447301/article/details/81207283