logback MDC

MDC (Mapped Diagnostic Context   映射诊断环境)

Logback的设计目标之一是审查和调试复杂的分布式应用程序。真实世界的多数分布式系统需要同时处理多个客户端。在一个典型的多线程方式实现的分布式系统里,不同的线程处理不同的客户端。区分不同客户端的记录输出的一个可行的但不好的方法是为每个客户端都创建新的、独立的logger。这种技术使logger的数量增多且大大增加了管理开销。

一个轻量的技术是为客户端的每个记录请求添加唯一戳(uniquely stamp)。Logback在SLJ4J里使用了这种技术的一种变体:映射诊断环境(MDC)。

为了给每个请求添加唯一戳,用户把环境(context)信息放进MDC。MDC类的重要部分如下,更多方法请参阅MDC的javadocs文档:

 

 

MDC类只有静态方法,开发者可以把信息放进一个诊断环境,之后用其他logback组件获取这些信息。MDC是基于每个线程进行管理的。子线程自动继承其父的映射诊断环境的一个副本。典型地,当开始为新的客户端请求服务时,开发者会向MDC里插入恰当的环境信息,比如客户端id、客户端IP地址、请求参数等等。Logback组件会自动在每个记录条目里包含这些信息。

下面的程序impleMDC演示了这一基本原则。

示例:MDC基本用法

( logback-examples/src/main/java/chapters/mdc/

 main()方法先在MDC里关联键“first”和值“Dorothy”。你可以在MDC里放入任何数量的键/值对。同名的键会覆盖旧键的值。代码接着配置logback。

为了简洁,我们忽略了用配置文件simpleMDC.xml对logback进行配置的代码,下面是配置文件里的相关部分:

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> 
<layout> 
<Pattern>%X{first} %X{last} - %m%n</Pattern> 
</layout> 
</appender>

 注意“%X”在PatternLayout里的用法。“%X”用了两次,一次是为键“first”,一次是为键“last”。代码先取得对应于“SimpleMDC.class”的logger,接着为键“last”关联一个值“Parker”,然后用不同的消息两次调用logger,最后把MDC设为其他值并执行几条记录请求。

运行SimpleMDC,输出:

Dorothy Parker - Check enclosed. 

Dorothy Parker - The most beautiful two words in English. 

Richard Nixon - I am not a crook. 

Richard Nixon - Attributed to the former US president. 17 Nov 1973.

SimpleMDC程序演示了logback的layout如何自动输出MDC信息。而且,放在MDC里的信息能被logger多次使用。

映射诊断环境在客户端-服务器模式下最有奇效。典型情况是,多个客户端被服务器的多个线程所处理。虽然MDC里的方法都是静态的,但MDC是基于每个线程进行管理的,这允许服务器的每个线程都有自己独立的MDC戳。MDC的操作,比如put()和get(),只作用于当前线程和当前线程的子线程,不影响其他线程里的MDC。由于MDC的信息是基于每个线程进行管理的,因此每个线程都有自己的MDC副本。所以在使用MDC时,开发者不需要操心线程安全或同步,因为MDC透明地、安全地处理了这些问题。

MDC 可以看成是一个与当前线程绑定的哈希表,可以往其中添加键值对。MDC 中包含的内容可以被同一线程中执行的代码所访问。当前线程的子线程会继承其父线程中的 MDC 的内容。当需要记录日志时,只需要从 MDC 中获取所需的信息即可。MDC 的内容则由程序在适当的时候保存进去。对于一个 Web 应用来说,通常是在请求被处理的最开始保存这些数据。

猜你喜欢

转载自huangqiqing123.iteye.com/blog/2393530