`

slf4j中的MDC

阅读更多

一.slf4j中MDC是什么

  slf4j除了trace、debug、info、warn、error这几个日志接口外,还可以配合MDC将数据写入日志。换句话说MDC也是用来记录日志的,但它的使用方式与使用日志接口不同。

  在使用日志接口时我们一般这么做

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行:

@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}:

<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.使代码简洁、日志风格统一

 

四.MDC实践

  我们从《log4j2在SpringMVC工程中的运用》中下载SpringMVC.zip工程,导入到Eclipse中。

  1.增加LogUtils.java

package com.bijian.study.utils;

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

import java.lang.invoke.MethodHandles;

public class LogUtils {
	
    private static Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

    public static void putMDC(String traceId) {
        try {
        	MDC.put("mdc_trace_id", traceId);
        } catch (Exception e) {
            log.error("MDCUtil.putMDC happen error", e);
        }
    }

    public static void removeMDC() {
        try {
            MDC.remove("mdc_trace_id");
        } catch (Exception e) {
            log.error("MDCUtil.removeMDC happen error", e);
        }
    }
}

  2.修改HelloController.java,在请求的入口加上LogUtils.putMDC(uuid.toString()),在请求结束加上LogUtils.removeMDC();

@ResponseBody
@RequestMapping("/greet")
public Map<String, Object> greet(HttpServletRequest request, HttpServletResponse response,
		@RequestParam(value = "name", defaultValue = "World") String name) {
	
	UUID uuid = UUID.randomUUID();
	LogUtils.putMDC(uuid.toString());
	Map<String, Object> map = null;
	try {
		//由于浏览器会把中文直接换成ISO-8859-1编码格式,如果用户在地址打入中文,需要进行如下转换处理
		String tempName = new String(name.getBytes("ISO-8859-1"), "utf-8");
		
		logger.trace("tempName:" + tempName);
		logger.info(tempName);

		String userName = helloService.processService(tempName);

		map = new HashMap<String, Object>();
		map.put("userName", userName);
		
		logger.trace("运行结果:" + map);
	} catch (UnsupportedEncodingException e) {
		logger.error("HelloController greet方法发生UnsupportedEncodingException异常:" + e);
	} catch (Exception e) {
		logger.error("HelloController greet方法发生Exception异常:" + e);
	}
	LogUtils.removeMDC();
	return map;
}

  3.修改log4j2.xml,增加[%X{mdc_trace_id}]配置


  4.启动Tomcat,浏览器中输入http://localhost:8080/SpringMVC/greet回车,日志输出如下所示

15:03:27.874 TRACE com.bijian.study.controller.HelloController[fceb3814-e400-4b86-939c-4e6aee1dc1aa] 67 greet - tempName:World
15:03:27.885 INFO  com.bijian.study.controller.HelloController[fceb3814-e400-4b86-939c-4e6aee1dc1aa] 68 greet - World
15:03:27.885 INFO  com.bijian.study.service.impl.HelloServiceImpl[fceb3814-e400-4b86-939c-4e6aee1dc1aa] 17 processService - HelloService processService name:World
15:03:27.886 TRACE com.bijian.study.controller.HelloController[fceb3814-e400-4b86-939c-4e6aee1dc1aa] 75 greet - 运行结果:{userName=Hello World}
15:03:40.878 TRACE com.bijian.study.controller.HelloController[1899a285-52fa-4b56-8e88-d230086f129f] 67 greet - tempName:World
15:03:40.880 INFO  com.bijian.study.controller.HelloController[1899a285-52fa-4b56-8e88-d230086f129f] 68 greet - World
15:03:40.881 INFO  com.bijian.study.service.impl.HelloServiceImpl[1899a285-52fa-4b56-8e88-d230086f129f] 17 processService - HelloService processService name:World
15:03:40.881 TRACE com.bijian.study.controller.HelloController[1899a285-52fa-4b56-8e88-d230086f129f] 75 greet - 运行结果:{userName=Hello World}

  其中,fceb3814-e400-4b86-939c-4e6aee1dc1aa和1899a285-52fa-4b56-8e88-d230086f129f就是mdc_trace_id。

 

   整个工程见附件《SpringMVC.zip》。

  参考文章:https://www.cnblogs.com/sealedbook/p/6227452.html

  • 大小: 39.3 KB
分享到:
评论

相关推荐

    slf4j jar包

    org.slf4j.MDC.class org.slf4j.Marker.class org.slf4j.MarkerFactory.class org.slf4j.helpers.BasicMDCAdapter.class org.slf4j.helpers.BasicMarker.class org.slf4j.helpers.BasicMarkerFactory.class org.slf4...

    slf4j-1.7.rar

    1.如果运行程序出现错误:“Exception in thread "main...3.错误:“Exception in thread "main" java.lang.NoSuchMethodError: org.slf4j.MDC.getCopyOfContextMap()Ljava/util/Map”,这是因为jar包版本冲突造成的。

    slf4j-api-1.6.2.jar

    org.slf4j.MDC.class org.slf4j.Marker.class org.slf4j.MarkerFactory.class org.slf4j.helpers.BasicMDCAdapter.class org.slf4j.helpers.BasicMarker.class org.slf4j.helpers.BasicMarkerFactory.class org.slf4...

    slf4j的jar包(54个)

    8. **slf4j-ext.jar**:这个扩展库包含了SLF4J的一些高级特性,如参数化日志、位置感知和MDC(Mapped Diagnostic Context)支持。 9. **不同版本的jar包**:可能包含不同版本的SLF4J及其绑定库,用于兼容不同版本的...

    slf4j 1.7 所有jar包

    SLF4J(Simple Logging Facade for Java)是Java中的一种日志抽象层,它提供了一个简单的API,允许开发者在应用程序中使用各种日志框架,如Log4j、Logback等,而无需直接依赖特定的日志实现。SLF4J 1.7是其的一个...

    slf4j-1.7.12

    7. **调试和诊断**:SLF4J提供了方便的调试工具,如`MDC`(Mapped Diagnostic Context)和`NDC`(Nested Diagnostic Context),它们可以存储上下文相关的数据,帮助开发者更好地跟踪和理解日志信息。 8. **最佳...

    Slf4j日志相关jar包

    5. **MDC(Mapped Diagnostic Context)**: Slf4j提供的一个特性,允许存储与当前线程相关的诊断信息,这对于跟踪和调试多线程应用程序非常有用。 **Log4j简介** Log4j是Apache的一个开源项目,是Java平台上的一个...

    slf4j 1.6.1所有jar包

    这个“slf4j 1.6.1所有jar包”包含了SLF4J API和其他绑定实现,包括slf4j-api-1.6.1、slf4j-simple-1.6.1和slf4j-jdk14-1.6.1。这些组件协同工作,为Java应用程序提供灵活的日志记录能力。 **SLF4J API(slf4j-api-...

    slf4J的所有相关jar

    7. **slf4j-ext.jar**:这个库包含了SLF4J的扩展功能,如MDC(Mapped Diagnostic Context)和NDC(Nested Diagnostic Context)的支持。 8. **jcl-over-slf4j.jar**:这是一个兼容接口,用于桥接Jakarta Commons ...

    slf4j相关jar包

    至于压缩包中的"SLF4J.txt"可能是SLF4J的使用指南或API文档,而"slf4j-1.5.6"可能是SLF4J的某个版本的jar包,比如SLF4J API或者绑定到特定日志库的实现。 在实际项目中,为了正确使用SLF4J,还需要确保没有其他的...

    slf4j与其它日志api的结合

    此外,SLF4J还提供了诸如MDC(Mapped Diagnostic Context)这样的高级功能,便于在日志中传递上下文信息,这对于大规模分布式系统中的日志追踪非常有用。 总结来说,SLF4J是一个重要的日志抽象层,它允许开发者编写...

    slf4j-1.7.22

    3. **MDC和NDC**:SLF4J提供了`Mapped Diagnostic Context`(MDC)和`Nested Diagnostic Context`(NDC)功能,帮助开发者在日志中添加上下文信息。MDC主要用于存储和检索键值对,而NDC则允许按层次结构添加信息,...

    log4j-slf4j-impl.zip

    "Log4j-slf4j-impl.zip"这个压缩包中包含的是Log4j对SLF4J接口的实现,即"log4j-slf4j-impl-2.11.2.jar"。SLF4J提供了一组API,允许开发者编写与具体日志库无关的日志代码。而Log4j-SLF4J-Impl则是SLF4J的一个绑定,...

    slf4j1.6.1-1.6.4.zip

    8. **MDC和NDC**:SLF4J支持MDC(Mapped Diagnostic Context)和NDC(Nested Diagnostic Context),这两种上下文信息可以用来跟踪和诊断问题,比如存储线程相关的调试信息。 9. **异常处理**:SLF4J允许直接传递...

    slf4j-api-1.6.3

    5. **MDC和NDC**:Mapped Diagnostic Context (MDC) 和Nested Diagnostic Context (NDC) 是SLF4J提供的两种上下文信息管理机制,用于添加和检索线程相关的诊断信息,帮助跟踪和调试问题。 6. **日志配置**:虽然SLF...

    最新的slf4j-1.7.6

    5. **MDC和NDC**:SLF4J支持Mapped Diagnostic Context (MDC)和Nested Diagnostic Context (NDC),这两者可以帮助记录和追踪日志上下文信息,如线程ID、请求ID等。 6. **日志配置**:虽然SLF4J本身不提供配置,但与...

    slf4j-1.5.8.zip

    5. **API扩展**:除了基本的日志方法,SLF4J还提供了一些高级特性,如`MDC (Mapped Diagnostic Context)`和`NDC (Nested Diagnostic Context)`,它们分别用于存储与线程相关的诊断信息和堆叠跟踪信息。 6. **兼容性...

    slf4j-1.5.2架包(完整版)

    5. **MDC和NDC**:SLF4J支持MDC(Mapped Diagnostic Context)和NDC(Nested Diagnostic Context),这两种上下文可以帮助在日志中添加环境相关的数据,如线程ID、请求ID等,以便于调试和追踪。 6. **日志配置**:...

    slf4j.api-1.6.1.jar

    6. **MDC与NDC**:SLF4J提供了Mapped Diagnostic Context (MDC)和Nested Diagnostic Context (NDC)功能,用于存储与日志相关的上下文信息,如线程ID、请求ID等,这对于追踪问题和调试非常有帮助。 7. **日志配置**...

Global site tag (gtag.js) - Google Analytics