Log4j的中文文档

Short introduction to log4j

Ceki Gülcü

March 2002

译者声明:<o:p></o:p>

1.       这是根据最新的log4j(jakarta-log4j-1.2.8)的开发包自带文档的manual翻译的<o:p></o:p>

2.       译者尽力保持原文格式,以便于读者查找原文<o:p></o:p>

3.       对一些关键词都带有原文单词,便于阅读<o:p></o:p>

4.       原文中比较生僻的单词,译者都是参考金山词霸,对找不到的组合词都是保持原文。<o:p></o:p>

5.       对比较拗口的说法,译者尽量采用意译的方法,同时保持原文。<o:p></o:p>

6.       有几个地方是log4j知识的深入探讨,翻译的不是很好,以后会重新修改<o:p></o:p>

2004618<o:p></o:p>

译文:<o:p></o:p>

版权所有2000-2002Apache软件组织。保留一切权利。这个软件是在Apache软件许可证1.1版本条款的保护下发布的。这个协议的内容都包含在LICENSE.txt文件中随log4j一起发布的。这份文档是基于2000年11月JavaWorld发表的"Log4j delivers control over logging"文章。然而,目前这篇文章包含更详细的内容和最近的信息。这篇文章也从同一个作者所著的"The complete log4j manual"借鉴了一些内容。

摘要

这篇文章描述了Log4j的API、独一无二的特色和设计原理。Log4j是一个聚集了许多作者劳动成果的开源软件项目。它允许开发人眼以任意的粒度输出日志描述信息。它利用外部的配置文件,在运行时是完全可配置的。最厉害的是,log4j有一条平滑的学习曲线。当心:从用户的反馈表明,它是很容易上瘾的。

介绍

几乎每个大型的应用程序都包含有自己的日志记录或跟踪API。与这个原则一致,E.U. SEMPER项目决定写自己的跟踪API。这事发生在1996年。在多次改进以后,经过几次演化和大量的工作使之逐渐变成了log4j,一个流行java日志包。这个软件包是在apache软件许可证的保护下发布的,开源组织主动性保证了这是一个完整的开源许可证。最新的log4j版本包含了源代码、类文件和可以在http://jakarta.apache.org/log4j/找到的文档。顺便说一下,log4j已经被发展到了C, C++, C#, Perl, Python, Ruby,和Eiffel语言。

在代码里插入日志描述代码是一种低级的调试方法。由于调试器并不总是可用的或者可应用的,因此这可能是唯一的方法。这对多线程应用和分布式应用来说是非常普遍的现象。

经验表明日志是开发环节中一个重要的组件。它提供了好多的有点。对一个正在运行的应用程序而言,它可以提供准确的环境信息。一旦插入了代码,日志输出就不需要认为的干涉。还有,日志输出可以保存在永久的媒体中,供以后研究。包括它在开发环节的作用,一个高效的功能丰富的日志包可以被看作一款审计工具。

就像Brian W. Kernighan和Rob Pike在他们的扛鼎之作《编程实践》中写下的

 

日志代码有它自己的缺点。它可能会导致应用程序运行变慢。假如输出太详细,可能会导致屏幕闪动(scrolling blindness)。为了减轻这些影响,log4j被设计为可依赖的,更快的和可扩展的。由于日志很少是应用程序关注的焦点,所以log4j API力争做到简单并易于理解和使用。

记录器(Loggers),输出源(Appenders)和布局器(Layouts)

Log4j包含三个首要组件:记录器,输出源和布局器。这三类组件一起工作使开发者可以按消息的类别和等级来输出消息,并且控制在运行时这些消息怎么格式化和在哪里输出这些信息。

记录器层次

任意一个log4j API最大的优点是平滑了System.out.println固有的能力,当允许其他人不受妨碍的打印时使某些日志语句不起作用。这个能力假定日志空间,也就是所有的可能的日志语句的空间,是可以按照开发者的标准来分类的。这个观察资料以前已经引导我们选择类别作为包的中心概念。然而,自从 log4j的1.2版本,记录器(Logger)类已经取代了范围(Category)类,对那些熟悉log4j早期版本的人来说,记录器(Logger)类可以被认为仅仅是范围(Category)类的别名(alias)。

记录器被命名为实体(Loggers are named entities),记录器(Logger)的命名是事件敏感的(case-sensitive),并且他们遵循层次的(hierarchical)命名规则:

按层次命名

假如一个记录器的名称后面跟着一个被认为是子记录器前缀的“.”号,那么它就被认为是另一个记录器的祖先

例如,名称为“com.foo”的记录器是名称为“com.foo.Bar”的父。相似的是,“java”是“java.util”的父,是“java.util.Vector”的祖先。这个命名规则对大多数的开发人员来说应该是很熟悉的

根记录器(root logger)处于记录器层次的顶端.在两种情况下,它是意外的。

1.       它总是存在

2.       它不可以通过名称获得

调用类的静态方法Logger.getRootLogger获得根类.所有其他类都被实例化,并且用类的静态方法Logger.getLogger获得这些实例。这个方法用期望的记录器作为参数。记录器类的一些基本方法如下:

记录器可以被设置级别。可能的级别包括DEBUG, INFO, WARN, ERROR和FATAL,这些级别被定义在org.apache.log4j.Level类中。尽管我们不鼓励,但是你还是可以通过子类化级别类来定义你自己的级别。一个更好的方法将在后面介绍

假如一个给定的记录器没有被设置级别,它可以集成一个最近的带有指定级别的祖先。更正式地:

Level Inheritance 级别继承

继承的级别被指定给记录器类C,在记录器层次中它是和第一个非空级别相等的

为了保证所有的记录器最终可以继承一个级别,根记录器总是有一个被指定的记录器。

下面是四个表,这些表带有不同指定级别值和参照上面规则的继承级别的结果

记录器名称<o:p></o:p>

指定的级别<o:p></o:p>

继承的级别<o:p></o:p>

root<o:p></o:p>

Proot<o:p></o:p>

Proot<o:p></o:p>

X <o:p></o:p>

none<o:p></o:p>

Proot<o:p></o:p>

X.Y <o:p></o:p>

none<o:p></o:p>

Proot<o:p></o:p>

X.Y.Z<o:p></o:p>

none<o:p></o:p>

Proot<o:p></o:p>

范例 1<o:p></o:p>

在上面的范例1中,仅仅根记录器被指定了级别。这个级别的值是Proot,它被其它的记录器X, X.Y和X.Y.Z继承

记录器名称<o:p></o:p>

指定的级别<o:p></o:p>

继承的级别<o:p></o:p>

root<o:p></o:p>

Proot<o:p></o:p>

Proot<o:p></o:p>

X <o:p></o:p>

Px<o:p></o:p>

Px<o:p></o:p>

X.Y <o:p></o:p>

Pxy<o:p></o:p>

Pxy<o:p></o:p>

X.Y.Z<o:p></o:p>

Pxyz<o:p></o:p>

Pxyz<o:p></o:p>

范例 2<o:p></o:p>

在范例2中所有的记录器都有一个指定的级别值,这就没有必要继承级别值了。

记录器名称<o:p></o:p>

指定的级别<o:p></o:p>

继承的级别<o:p></o:p>

root<o:p></o:p>

Proot<o:p></o:p>

Proot<o:p></o:p>

X <o:p></o:p>

Px<o:p></o:p>

Px<o:p></o:p>

X.Y <o:p></o:p>

none<o:p></o:p>

Px<o:p></o:p>

X.Y.Z<o:p></o:p>

Pxyz<o:p></o:p>

Pxyz<o:p></o:p>

范例 3<o:p></o:p>

在范例3中,所有的记录器,包括X 和 X.Y.Z都被分别指定记录器值为Proot、Px和Pxyz。记录器X.Y从它的父X继承它的级别值

记录器名称<o:p></o:p>

指定的级别<o:p></o:p>

继承的级别<o:p></o:p>

root<o:p></o:p>

Proot<o:p></o:p>

Proot<o:p></o:p>

X <o:p></o:p>

Px<o:p></o:p>

Px<o:p></o:p>

X.Y <o:p></o:p>

none<o:p></o:p>

Px<o:p></o:p>

X.Y.Z<o:p></o:p>

none<o:p></o:p>

Px<o:p></o:p>

范例 4<o:p></o:p>

 <o:p></o:p>

在范例4中,记录器root和X分别被指定级别值为Proot和Px。记录器X.YX.Y.Z从最接近它们的父X继承它们的级别值,这个父有一个指定的级别值…

通过调用一个记录器实例的打印方法来处理日志请求。这些打印方法是debug, info, warn, error, fatallog.

通过定义,打印方法决定一个日志请求的级别。例如,假如c是一个记录器实例,语句c.info("..")是一个带有INFo级别的日志请求。

若日志请求的级等于或者大于日志记录器的级别,那么这个日志请求就是可行的,相反,请求将不能输出。一个没有被指定级别的日志记录器将从层次(hierarchy)继承。这些规则在下面总结。

基本的选择规则

在一个具有q级别的日志记录器中(指定和继承都是合适的)有一个具有p级别的日志请求,若p>=q,则这个日志请求是可以输出的。

这个规则是log4j的核心。假定级别是排序的,对标准的级别来说,我们设定DEBUG < INFO < WARN < ERROR < FATAL。

用同一个名称调用getLogger方法将返回一个指向同一个记录器对象的引用

例如,

xy指向同一个日志记录器对象

因此,配置一个日志记录器,不用在代码里转换引用就可以获得相同的实例是可能的。在生物学父时代的基本矛盾里面,总是可以preceed他们的孩子,log4j的日志记录器可以按一定的规则创建和配置。尤其是,即使一个“父”日志记录器在它的子孙后面被实例化,它仍然可以发现并连接到它的子孙

在应用程序初始化的时候,Log4j的配置被执行。最好的方法是通过读取一个配置文件。很快就会讨论这个方法

通过使用软件组件,log4j很容易命名日志记录器。这可以通过在每个类中静态实例化日志记录器来完成,日志记录器名是和完整的类名相同的。这是一个直截了当地定义日志记录器的有用方法。由于日志输出带有产生该日志的日志记录器的名称,命名策略让辨认产生日志消息的源头很容易。然而,这仅仅是是一个可能,虽然命名日后子记录器的策略很普通(However, this is only one possible, albeit common, strategy for naming loggers)。Log4j没有约束日志记录器可能趋势(Log4j does not restrict t

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值