NDC
和
MDC
NDC
(
Nested Diagnostic Context
)和
MDC
(
Mapped Diagnostic Context
)是
log4j
种非常有用的两个类,它们用于存储应用程序的上下文信息(
context infomation
),从而便于在
log
中使用这些上下文信息。
NDC
采用了一个类似栈的机制来
push
和
pop
上下文信息,每一个线程都独立地储存上下文信息。比如说一个
servlet
就可以针对每一个
request
创建对应的
NDC
,储存客户端地址等等信息。
当使用的时候,我们要尽可能确保在进入一个
context
的时候,把相关的信息使用
NDC.push(message);
在离开这个
context
的时候使用
NDC.pop()
将信息删除。另外由于设计上的一些问题,还需要保证在当前
thread
结束的时候使用
NDC.remove()
清除内存,否则会产生内存泄漏的问题。
存储了上下文信息之后,我们就可以在
log
的时候将信息输出。在相应的
PatternLayout
中使用
”%x”
来输出存储的上下文信息,下面是一个
PatternLayout
的例子:
%r [%t] %-5p %c{2} %x - %m%n
MDC
和NDC非常相似,所不同的是MDC内部使用了类似map的机制来存储信息,上下文信息也是每个线程独立地储存,所不同的是信息都是以它们的key值存储
在”map”中。相对应的方法,MDC.put(key, value); MDC.remove(key); MDC.get(key);
在配置PatternLayout的时候使用:%x{key}来输出对应的value。同样地,MDC也有一个
org.apache.log4j.filters.MDCMatchFilter。这里需要注意的一点,MDC是线程独立的,但是一个子线程会自动获得
一个父线程MDC的copy。
至于选择NDC还是MDC要看需要存储的上下文信息是堆栈式的还是key/value形式的。
DSW 实践是在servlet入口将user ID 放入MDC中,然后配置log4j 的patternLayout打印user ID, 在serverlt出口前remove以防内存泄露。
动态修改日志配置
在开发过程中,我们经常会遇到修改log4j配置的情况,在这种情况下,频繁重启应用显然是不可接受的。幸好log4j提供了自动重新加载配置文件的能力,在配置文件修改后,便会自己重新加载配置。在1.2及以前的版本中
DOMConfigurator
和
PropertyConfigurator
都提供了
configureAndWatch
方法,对指定的配置文件进行监控,并且可以设置检查的间隔时间。