log4j NDC 用法小例子

来源:互联网 发布:票房数据排行榜 编辑:程序博客网 时间:2024/05/22 13:10

性能

在记录一些日志信息时,会一定程度地影响系统的运行效率,这时日志工具是否高效就是一个关键。Log4J的首要设计目标就是高效,一些关键组件都重写过很多次以不断提高性能。根据Log4J项目小组的报告,在AMD Duron 800MHz + JDK1.3.1的环境下,Log4J判断一条日志语句是否需要输出仅需要5纳秒。实际的日志语句执行的也非常快速,从使用SimpleLayout的21微秒(几乎与System.out.println一样快),到使用TTCCLayout的37微秒不等。

嵌套诊断环境NDC

在多用户并发的环境下,通常是由不同的线程分别处理不同的客户端请求。此时要在日志信息中区分出不同的客户端,你可以为每一个线程生成一个Logger,从而从一堆日志信息中区分出哪些信息是属于哪个线程的,但这种方式并不高效。Log4J巧妙地使用了Neil Harrison提出的“NDC(嵌套诊断环境)”机制来解决这个问题。Log4J为同一类别的线程生成一个Logger,多个线程共享使用,而它仅在日志信息中添加能够区分不同线程的信息。NDC是什么?举例来说,如果一个Servlet接到并发请求时,为每一个客户端创建一个新的线程,然后分配一个用于保存该请求上下文的NDC堆栈。该上下文可能是发出请求的主机名、IP地址或其它任何可以用于标识该请求的信息。这样,由于不同的客户端处理线程具有不同的NDC堆栈,即使这个Servlet同时生成多个线程处理不同的请求,这些日志信息仍然可以区分出来,就好像Log4J为每一个线程都单独生成了一个Logger实例一样。在Log4J中是通过org.apache.log4j.NDC实现这种机制的。使用NDC的方法也很简单,步骤如下:

1. 在进入一个环境时调用NDC.push(String),然后创建一个NDC;

2. 所做的日志操作输出中包括了NDC的信息;

3. 离开该环境时调用NDC.pop方法;

4. 当从一个线程中退出时调用NDC.remove方法,以便释放资源。

下面是一个模拟记录来自不同客户端请求事件的例子,代码如下:

import org.apache.log4j.Logger;import org.apache.log4j.NDC;public class TestNDC { static Logger log = Logger.getLogger(TestNDC.class.getName()); public static void main(String[] args) {  log.info("Make sure %x is in your layout pattern!");  // 从客户端获得IP地址的例子  String[] ips = {"192.168.0.10","192.168.0.27"};  for (int i = 0; i<ips.length ; i++)  // 模拟一个运行方法  {   // 将IP放进 NDC中   NDC.push(ips[i]);   log.info("A NEW client connected, who's ip should appear in this log message.");   NDC.pop();  }  NDC.remove();  log.info("Finished."); }}

注意配置文件中的布局格式中一定要加上%x。系统输出如下:

INFO   - Make sure %x is in your layout pattern!INFO  192.168.0.10 - A NEW client connected, who's ip should appear in this log message.INFO  192.168.0.27 - A NEW client connected, who's ip should appear in this log message.INFO   - Finished.

使用Log4J还是JDK logging API

从JDK 1.4.0开始,引入了java.util.logging包。虽然Log4J小组曾竭力游说JCP(Java Community Process)采用Log4J作为JDK 1.4的“标准”日志API,虽然最终因Sun的日志API规范的负责人Graham Hamilton的一句“Merlin的开发已经到了最后阶段,这时不允许再对主要API做出改变”而没有被采纳,但Log4J还是对新的日志API产生了重要影响。那么,我们到底应该采用Log4J还是java.util.logging包呢?下面仅对两者做一简单的比较。

1. Log4J更加成熟,从1999年10月开始至今已经有3年的时间,并且已经在许多项目中有着成熟的应用。而JDK中的logging包是在1.4之后才引入的,并且不能运行于JDK 1.3之前的版本。Log4J则可以良好地运行于JDK 1.1之后的所有版本。

2. Log4J已经被移植到多种环境下,包括log4c(C)、log4cpp(C++)、log4perl(Perl)、log4net(.net)等。在这些环境下,可以感受到几乎一致的配置和使用方式。这是JDK中的logging API所不能比拟的。

3. Log4J还具有更加强力的格式化系统,可以使记录输出时实现简单的模式。但是,它不会增加类而导致格式化工具的扩展。众多的附加程序和处理器使得Log4J数据包成为一个绝佳的选择,所有你所需要的都可能加以实现。

4. Log4J在性能上做了最大的优化。

Logging API对于简单的使用是足够的,但它缺少了许多Log4J所具有的功能。所以,如果你需要一个强力的logging机制,就应坚持使用Log4J;而如果只是需要一些简单的控制或文件记录,那么可以使用已经内建在JDK之中的logging API。

虽然Log4J和JDK logging API是一种竞争关系,但在logging API还在JCP中讨论(JSR47)时,两者之间就已经开始相互影响了。

0 0
原创粉丝点击