Log4j日志组件 - 终极资料

更新时间:2024-04-19 04:55:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

这个文档可以说集合了你的所有百度和google操作 最好你的英语好点,因为文档中有外国的文献

其实log4j的文档并不是免费的,同时网上的资料很多都是相同的 如果当你有一天觉得log4j不太方便了 可以考虑logback 这是后话

这份文档,可以说是log4j的终极文档 呵呵,算我夸张

5分下载,你们自己选择吧 好吧,不说了 联系方式: macrotea@qq.com

译文:

版权所有2000-2002Apache软件组织。保留一切权利。这个软件是在Apache软件许可证1.1版本条款的保护下发布的。这个协议的内容都包含在LICENSE.txt文件中随log4j一起发布的。这份文档是基于2000年11月JavaWor

ld发表的\文章。然而,目前这篇文章包含更详细的内容和最近的信息。这篇文章也从同一个作者所著的\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获得这些实例。这个方法用期望的记录器作为参数。记录器类的一些基本方法如下: package org.apache.log4j;

public class Logger {

// Creation & retrieval methods:

public static Logger getRootLogger();

public static Logger getLogger(String name);

// printing methods:

public void debug(Object message); public void info(Object message); public void warn(Object message); public void error(Object message); public void fatal(Object message);

// generic printing method:

public void log(Level l, Object message); }

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

假如一个给定的记录器没有被设置级别,它可以集成一个最近的带有指定级别的祖先。更正式地: Level Inheritance级别继承 继承的级别被指定给记录器类C,在记录器层次中它是和第一个非空级别相等的 为了保证所有的记录器最终可以继承一个级别,根记录器总是有一个被指定的记录器。 下面是四个表,这些表带有不同指定级别值和参照上面规则的继承级别的结果 记录器名称 指定的级别 继承的级别 root X X.Y X.Y.Z Proot none none none 范例 1 在上面的范例1中,仅仅根记录器被指定了级别。这个级别的值是Proot,它被其它的记录器X, X.Y和X.Y.Z继承 记录器名称 指定的级别 继承的级别 root X X.Y X.Y.Z Proot Px Pxy Pxyz 范例 2 在范例2中所有的记录器都有一个指定的级别值,这就没有必要继承级别值了。 记录器名称 指定的级别 继承的级别 root X X.Y X.Y.Z Proot Px none Pxyz 范例 3 在范例3中,所有的记录器,包括X 和 X.Y.Z都被分别指定记录器值为Proot、Px和Pxyz。记录器X.Y从它的父X继承它的级别值

记录器名称 指定的级别 继承的级别 root X X.Y X.Y.Z Proot Px none none 范例 4

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

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

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

若日志请求的级等于或者大于日志记录器的级别,那么这个日志请求就是可行的,相反,请求将不能输出。一个没有被指定级别的日志记录器将从层次(hierarchy)继承。这些规则在下面总结。 基本的选择规则 在一个具有q级别的日志记录器中(指定和继承都是合适的)有一个具有p级别的日志请求,若p>=q,则这个日志请求是可以输出的。 这个规则是log4j的核心。假定级别是排序的,对标准的级别来说,我们设定DEBUG < INFO < WARN < ERROR < FATAL。

// get a logger instance named \ Logger logger = Logger.getLogger(\); // Now set its level. Normally you do not need to set the // level of a logger programmatically. This is usually done // in configuration files. logger.setLevel(Level.INFO); Logger barlogger = Logger.getLogger(\); // This request is enabled, because WARN>= INFO. logger.warn(\ // This request is disabled, because DEBUG= INFO. barlogger.info(\ // This request is disabled, because DEBUG

Logger x = Logger.getLogger(\ Logger y = Logger.getLogger(\ x和y指向同一个日志记录器对象

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

在应用程序初始化的时候,Log4j的配置被执行。最好的方法是通过读取一个配置文件。很快就会讨论这个方法 通过使用软件组件,log4j很容易命名日志记录器。这可以通过在每个类中静态实例化日志记录器来完成,日志记录器名是和完整的类名相同的。这是一个直截了当地定义日志记录器的有用方法。由于日志输出带有产生该日志的日志记录器的名称,命名策略让辨认产生日志消息的源头很容易。然而,这仅仅是是一个可能,虽然命名日后子记录器的策略很普通(However, this is only one possible, albeit common, strategy for naming loggers)。Log4j没有约束日志记录器可能趋势(Log4j does not restrict the possible set of loggers)。开发者可以很自由的根据需要命名日志记录器。

不过,在类后面命名日志记录器好像是目前所知最好的策略 输出源和布局器

基于日志记录器有选择地让日志请求是否起作用地能力仅仅描述(picture)地一部分.log4j允许日志请求输出到多个目标。在log4j地声明中,输出目的地被成为输出源(appender).最近,输出源包括控制然台、文件、GUI组件、远程套接字服务器(remote socket servers)、JMS、NT事件记录器(NT Event Loggers)和远程UNIX Syslog守护进程(remote UNIX Syslog daemons)。它也可以异步地记录日志。 一个日志记录器可以有多个输出源。

AddAppender方法加一个输出源到给定的日志记录器。对应给定的日志记录器每个激活的日志请求都将被转向到所有的输出源,因为这些输出源是和层次 (hierarchy) 中更高级别的输出源一样的。换句话说,输出源是被从日志记录器的层次附加继承的(appenders are inherited additively from the logger hierarchy)。例如,假如有一个控制台输出源被加到一个根日志记录器(root logger),最后所有被激活的日志请求都将打印在控制台上,另外,假如一个文件输出源被加到日志记录器,叫做C,然后激活到C和C的孩子的日志请求将输出到一个文件和控制台。覆盖这个默认的行为是可能,以便于通过设定附加标识为假,输出源的聚集不再是附加的。 管理输出源附加行为的规则将在下面总结。 输出源的附加特性 日志记录器C的日志语句的输出将定向到C和它的祖先中的所有的输出源。这是条款“输出源的附加特性(appender additivity)”的意图. 然而,假如有一个日志记录器C的祖先,叫做P,有一个附加标识被设置为false,然后C的输出将被定向到C和直到C的祖先P(包括P)中的所有的输出源,但是不包括P的祖先的中的任何输出源。 日志记录器有它自己附加特性,该特性被默认设置为true 下表展示了一个例子:

日志记录器

添加的输出源 A1

附加特性标

识 not

输出目标 评论

root A1 根日志记录器是匿名的,但是可以用

applicable

Logger.getRootLogger()方法来存取。根日志记录器没有默认输出源。

A1, A-x1, A-x2 A1, A-x1, A-x2 A1, A-x1, A-x2, A-xyz1 A-sec

x

A-x1, A-x2

true x和根的输出源

x.y none true x和根的输出源

x.y.z A-xyz1 true x.y.z 、x和根的输出源

security A-sec false 由于附加标识被设置为false,没有输出源聚集 由于安全中附加标识被设置为false,所以仅仅有安全的输出源。

security.access none true A-sec

时常,用户不仅希望自定义目的地,而且包括输出格式的自定义。这是通过给输出源设定一个布局器(layout)来到达目的地。

例如,带有\转换格式的PatternLayout布局器将输出和下面的内容类似。 176 [main] INFO org.foo.Bar - Located nearest gas station.

第一个字段是自从程序开始到目前花费的时间。第二个字段是发出日志请求的线程。第三个字段是日志语句的级别。第四个是和该日志请求关联的日志记录器的名称。紧接着“-”符号后面的内容是日志语句的消息。

正像这样重要,log4j将按用户指定的标准修饰(render,这样翻译,不知是否合适)日志信息的内容。例如,假如你经常需要记录Oranges,这是一个在你当前项目中使用的对象类别,你可以注册一个OrangeRenderer类,在某个orang需要记录日志的时候将调用OrangeRenderer类

对象的修饰(Object rendering)遵循类层次。例如,假定oranges是水果,若你注册了一个FruitRenderer类,包括所有的oranges水果都将被FruitRenderer类修饰,除非你给orange指定一个OrangeRenderer。 renderer对象必须实现ObjectRenderer接口 配置

插入应用程序代码的日志请求需要相当大的准备和努力。观察表明大约有4%的代码是用来输出日志的。结果,即使适度大小的应用程序也有数以千计的日志语句被嵌在代码中。给定他们数字,管理这些语句变成了急迫的事情,而不需要没有手工修改的。

Log4j的环境是完全参数化的配置。然而,用配置文件配置log4j是非常灵活的。目前,配置文件可以使用XML或者java属性文件(键值)格式

然我们尝试一下怎样用log4j 配置一个虚构的应用程序MyApp。

import com.foo.Bar; // Import log4j classes. import org.apache.log4j.Logger; import org.apache.log4j.BasicConfigurator; public class MyApp { // Define a static logger variable so that it references the // Logger instance named \ static Logger logger = Logger.getLogger(MyApp.class); public static void main(String[] args) { // Set up a simple configuration that logs on the console. BasicConfigurator.configure(); logger.info(\ Bar bar = new Bar(); bar.doIt(); logger.info(\ } } MyApp从导入相关类开始。它然后使用MyApp定义了一个静态的日志记录器变量,这个MyApp恰好是一个完整的类名。

MyApp用到了定义在com.foo包中的Bar类

package com.foo; import org.apache.log4j.Logger; public class Bar { static Logger logger = Logger.getLogger(Bar.class); public void doIt() { logger.debug(\ } } BasicConfigurator.configure方法的调用创建了一个比较简单的log4j设置。这个方法是硬连线(hardwired)地添加到根日志记录器的ConsoleAppender输出源。输出将使用布局器PatternLayout来格式化,布局器PatternLayout被设定为\的格式。 注意默认值,根日志记录器被设定为Level.DEBUG级别。 MyApp的输出是:

0 [main] INFO MyApp - Entering application.

36 [main] DEBUG com.foo.Bar - Did it again! 51 [main] INFO MyApp - Exiting application.

下面这个图描述了在调用BasicConfigurator.configure 方后之后MyApp的对象图

作为一个侧面的注意点,我要提及的是log4j中的子类仅仅连接到他们存在的祖先。特别的,名为com.foo.Bar的日志记录器被直接连接到根日志记录器,因而围绕在未使用的com或者com.foo日志记录器。这个显著地提高了性能,并且减少了log4j地内存消耗(footprint)

MyApp类通过调用BasicConfigurator.configure方法来配置log4j。其他类仅仅需要导入org.apache.log4j.Logger,取回他们想要的日志记录器,并且在远处记录。

前面的例子总是输出相同的日志信息。幸运的是,很容易修改MyApp,以便可以在运行是控制日志输出。下面是一个稍微修改的版本

import com.foo.Bar; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; public class MyApp { static Logger logger = Logger.getLogger(MyApp.class.getName()); public static void main(String[] args) { // BasicConfigurator replaced with PropertyConfigurator. PropertyConfigurator.configure(args[0]); logger.info(\ Bar bar = new Bar(); bar.doIt(); logger.info(\ } } 这个版本的MyApp构造了PropertyConfigurator类来解析一个配置文件,因此建立日志

下面是一个配置文件的实例,这个配置文件导致输出和前面也基于这个实例的BasicConfigurator类的输出完全相同的。

# Set root logger level to DEBUG and its only appender to A1. log4j.rootLogger=DEBUG, A1 # A1 is set to be a ConsoleAppender. log4j.appender.A1=org.apache.log4j.ConsoleAppender # A1 uses PatternLayout. log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n 假定我们不再对com.foo包中任何组件的输出感兴趣。下面的配置文件展示了一个可能方法,利用这个方法可以完成这个任务。

log4j.rootLogger=DEBUG, A1 log4j.appender.A1=org.apache.log4j.ConsoleAppender log4j.appender.A1.layout=org.apache.log4j.PatternLayout # Print the date in ISO 8601 format log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n # Print only messages of level WARN or above in the package com.foo. log4j.logger.com.foo=WARN 用这个文件配置的MyApp的输出如下所示。

2000-09-07 14:07:41,508 [main] INFO MyApp - Entering application. 2000-09-07 14:07:41,529 [main] INFO MyApp - Exiting application.

由于日志记录器com.foo.Bar没有给定级别,它从com.foo继承它的级别,在配置文件中com.foo被设定为WARN。Bar.doIt方法的日志语句有DEBUG级别,这比日志记录器的级别的WARN低。因此doIt()方法的日志请求被禁止 下面是有多个输出源的配置文件。

log4j.rootLogger=debug, stdout, R log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout # Pattern to output the caller's file name and line number. log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n log4j.appender.R=org.apache.log4j.RollingFileAppender

log4j.appender.R.File=example.log log4j.appender.R.MaxFileSize=100KB # Keep one backup file log4j.appender.R.MaxBackupIndex=1 log4j.appender.R.layout=org.apache.log4j.PatternLayout log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n 用这个配置文件调用增强后的MyApp将在控制台上输出如下内容。 INFO [main] (MyApp2.java:12) - Entering application. DEBUG [main] (Bar.java:8) - Doing it again!

INFO [main] (MyApp2.java:15) - Exiting application.

In addition, as the root logger has been allocated a second appender, output will also be directed to the example.log file. This file will be rolled over when it reaches 100KB. When roll-over occurs, the old version of example.log is automatically moved to example.log.1.

另外,由于根日志记录器被分配给第二个输出源,输出将定向到example.log文件。当这个文件增展100KB时,将会翻转(rolled over)这个文件,当翻转发生时,老版本的example.log将被自动移到example.log.1文件 注意,为获得这些不同的日志行为,我们不必重编译代码。我们可以很简单记录UNIX Syslog进程,重定向com.foo所有的输出到一个NT事件记录器,或者定向日志事件到一个远程log4j服务器,这些都可以依照一个本地服务器规则记录日志,例如,可以通过定向一个日志事件到第二个log4j服务器。 默认的初始化进程

Log4j类库没有对它的环境作任何假设。特别是,log4j没有默认的输出源。然而,在某些定义明确的环境下,日志记录器类的静态的初始化器将尝试自动配置log4j。java语言保证在往内存中装载类时,类的静态初始化器仅仅可以被调用一次。不同类装载器可能装载相同类的不同拷贝,记住这是很重要的。Java虚拟机认为这些相同类的拷贝是完全不相关的。

在依赖运行环境的应用程序的正确入口处,默认的初始化是非常有用的。例如,在web服务器(web-server)的控制下,相同的应用程序可以被当作一个独立的应用程序、applet或者servlet。 下面定义的是确切的默认注视化算法:

1. 设定log4j.defaultInitO覆盖系统属性的为任何其它值,“false”将导致log4j忽略默认的初始化过程

(这个过程)。 2. 设定资源字符串变量为log4j.configuration的系统属性值。指定默认初始化文件的最好方法是通过lo

g4j.configuration的系统属性。万一系统属性log4j.configuration没有定义,可以设定字符串变量资源到它默认值“log4j.properties”。 3. 尝试转换资源变量为URL

4. 假如资源变量不能转换为URL,例如由于一个MalformedURLException异常,然后通过调用返回值为URL

的org.apache.log4j.helpers.Loader.getResource(resource, Logger.class)方法在classpath中查找资源。注意,字符串\包含(constitutes)一个丑陋的URL。

参考Loader.getResource(java.lang.String)方法,获得查找路径的列表。 5. 假如没有URL,忽略默认的初始化。其它,通过URL来配置log4j。

常常使用PropertyConfigurator类解析URL来配置log4j,若URL以“.xml”后缀名结束,将使用DOMConfigurator来解释。你可以有选择指定自定义的配置器。log4j.configuratorClass的系统属性值被当作你自定义配置器的完整类名。你所指定的自定义配置器必须实现Configurator接口。

配置实例

在Tomcat下的默认配置

在web服务器环境中,Log4j默认的初始化是特别有用的。在Tomcat 3.x 和 4.x下,你应该把log4j.properties放置在你web应用程序的WEB-INF/classes目录下。Log4会发现这个属性文件并自己进行初始化。这是很容易做的。 在tomcat启动之前,你也可以选择设置系统属性log4j.configuration。Tomcat 3.x的环境变量TOMCAT_OPTS被用来设置命令行选项。Tomcat 4.0设置CATALINA_OPTS环境变量替代TOMCAT_OPTS。 实例 1

Unix shell命令

输出TOMCAT_OPTS=\告诉log4j用文件foobar.txt作为默认的配置文件。这个文件应该被放置在你应用程序WEB-INF/classes的目录下。每个web应用程序将用一个不同的默认配置文件,因为每个文件都是和相对web应用程序的 实例 2

Unix shell命令

输出TOMCAT_OPTS=\告诉log4j输出log4j的内部调试信息,并用文件foobar.xml作为默认的配置文件。这个文件应该被放置在你应用程序WEB-INF/classes的目录下。由于文件是以.xml后缀结束的,所以它将使用DOMConfigurator来读文件。每个web应用程序将用一个不同的默认配置文件,因为每个文件都是和相对web应用程序的 实例 3

Windows shell命令

设置TOMCAT_OPTS=-Dlog4j.configuration=foobar.lcf -Dlog4j.configuratorstyle=\宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'\告诉log4j用文件foobar.lcf作为默认的配置文件。由于log4j.configuratorClass这个系统属性的定义,文件将用com.foo.BarConfigurator定义的配置器(configurator)来读取。每个web应用程序将用一个不同的默认配置文件,因为每个文件都是和相对web应用程序的 实例 4

Windows shell命令

设置TOMCAT_OPTS=-Dlog4j.configuration=file:/c:/foobar.lcf告诉log4j用文件c:\\foobar.lcf作为默认的配置文件。配置文件被完整指定通过用URL文件:/c:/foobar.lcf。因此所有的应用程序都使用相同的配置文件。 不同的web应用程序将通过他们各自的类加载器(classloaderss)来加载log4j类。因此,log4j环境的每个映象(image)是独立执行的,并且不需要任何相互同步。例如,FileAppenders在多个web应用程序配置中定义相同的方法,这将全部写入相同的文件。这个结果很可能是不太让人满意的。你必须确保不同web应用程序的log4j配置不用相同的潜在系统资源。 初始化servlet

用一个特殊的servlet平日之log4j也是可能的。下面是一个例子 package com.foo; import org.apache.log4j.PropertyConfigurator; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.PrintWriter; import java.io.IOException; public class Log4jInit extends HttpServlet { public void init() { String prefix = getServletContext().getRealPath(\ String file = getInitParameter(\ // if the log4j-init-file is not set, then no point in trying if(file != null) { PropertyConfigurator.configure(prefix+file); } } public void doGet(HttpServletRequest req, HttpServletResponse res) { } } 在你的web应用程序的web.xml文件中定义下面servlet log4j-init com.foo.Log4jInit log4j-init-file WEB-INF/classes/log4j.lcf 1 写一个初始化的servlet是初始化log4j的最灵活方法 嵌套诊断环境

大多数的现实世界的系统必须能并发地处理多个客户端。在这样一个典型的多线程系统中,不同线程将处理不同客户端。记录日志是特别适于跟踪和调试复杂的分布式应用程序。从一个客户端区分出另一个客户端的日志输出的简单方法是给每个客户端实例化以日志记录器。这将导致日志记录器的增加,并且增加了整个日志的维护工作。 一个简单的技术是对每个从相同客户端交互发出日志请求都有独一无二的时间戳。Neil Harrison在《Patterns for Logging Diagnostic Messages》书的Pattern Languages of Program Design 3(edited by R. Martin, D. Riehle, and F. Buschmann (Addison-Wesley, 1997))中描述了这个方法。

每个请求都有唯一的时间戳,使用者把环境信息压进NDC,NDC是Nested Diagnostic Context的缩写。NDC类如下所示。

public class NDC {

// Used when printing the diagnostic publicstatic String get();

// Remove the top of the context from the NDC. publicstatic String pop();

// Add diagnostic context for the current thread. publicstatic void push(String message);

// Remove the diagnostic context for this thread. publicstatic void remove(); }

每个线程把NDC当作环境信息堆栈来管理。注意,org.apache.log4j.NDC类的所有的方法都是静态的。假定NDC打印是被证明了的,每次一个日志请求被处理,在日志输出信息中,适当的log4j组件将包含当前线程的完整NDC堆栈。这个在没有用户感受的情况下完成,这个用户负责的仅仅是通过在代码的某些定义明确的点使用push和pop方法,在NDC中放置正确的信息,

为了说明这一点,让我们举一个例子,这个例子是servlet分发内容到许多客户端。在执行其他代码之前Servlet可以在请求开始的时候编译NDC。环境信息可能是客户端主机的名字和请求内在的其他信息,典型的是包含cookie的信息。因此,即使sevlet在同时服务多个客户端,日志也会通过相同的代码开始记录,也就是说,即使依附于相同的日志记录器,由于每个客户顿请求包含不同的NDC堆栈,日志仍然是可以区分的。

然而,一些健壮的应用程序,例如虚拟主机web服务器,必须根据不同的虚拟主机环境和请求中的软件组件,记录不同不同信息。最近log4j发布的版本开始支持多层次树。这个提高允许每个虚拟主机拥有它自己的日志记录器层次的拷贝 性能

经常提到的放对日志记录的是计算消耗。这是一个合理的关注,即使适度大小的应用程序也可能产生数以千计的日志请求。大量工作被花费在调节和提高日志的性能上。Log4j主张快和灵活:速度第一,灵活性第二。

The user should be aware of the following performance issues. 用户应该注意下面的性能问题

1. 当关闭日志时的日志性能。

当日志被完全关掉的时候,或者恰恰设置为一个级别,日志请求的消耗包括一个方法调用和一个整型比较。在以233 MHz Pentium II的机子上,消耗在5到50纳秒范围内。 然后,方法调用隐含了参数构造的“隐形”消耗。 例如,一些日志记录器,如下,

logger.debug(\

构造消息参数导致消耗,也就是,转换整型I和数组entry[i]为字符串,还有连接媒介字符串,不论消息是否记录。这个参数转换的消耗可能时非常高的,并且依赖于转换参数的大小。 避免构造参数消耗的写法:

if(logger.isDebugEnabled() {

logger.debug(\ }

这个将不会导致构造参数的消耗,假如调试器是不可用的。另一方面,假如日志记录器是可调试的,无论日志记录器是否可用,它将导致两次计算消耗。这是一个无关紧要的费用(overhead),因为评估(evaluating)一个日志记录器的消耗大约是日志记录器真正消耗的1%。

在log4j里面,日志请求是由日志记录器实例处理的。日志记录器是一个类而不是一个接口。这就显著地减少方法调用的消耗,当然这是以灵活性为代价的(This measurably reduces the cost of method invocation at the cost of some flexibility)。

某些用户利用预处理或者实时编译技术编译所有的日志语句。这将导向优秀的性能效率而不影响日志记录。然而,由于应用程序二进制不包含任何日志语句,日志记录不可能变成二进制(logging cannot be turned on for that binary)。我的观点,这是一个不成比例的代价,为获得小性能的提高。 2. 当日志记录开始启动,决定是否记录日志的性能

跨越日志记录器层次的性能是潜在的。当日志记录开始时,log4j将需要比较日志请求和日志请求处理器的级别。然而,日志记录器不可以有指定的级别;他们可以从日志记录器层次继承级别。因此。在继承一个级别前,日志记录器可能需要搜索它的祖先。

已经花费大量努力让跨越这个层次尽可能的快。例如,子日志记录器仅仅连接到他们存在的祖先。在早先展示的BasicConfigurator实例中,名为com.foo.Bar的日志记录器被直接连接到根日志记录器,因此回避了com和com.foo的不存在。这显著地提高了跨越地速度,特别是在“稀疏的”层次关系 跨越层次的典型消耗比日志记录被完全关闭的时候大约慢3倍。 3. 真正地输出信息

这是格式化日志输出并把它发向目标的消耗。在这儿,大量的努力再次被花费在让布局器(格式化器)执行尽可能地快。这是和输出源相同地。真正地记录日志的典型消耗大约从100到300微秒。参考org.apache.log4.performance.Logging获得准确数字。

尽管log4j有许多特点,但是它的首要目标是速度。为了提高性能,一些log4j组件已经被重写了好多次了。然而,贡献者还在不断地提出新地优化。你应该很高兴,当你知道使用SimpleLayout配置记录日志时,测试显示log4j和System.out.println地速度一样快。 结论

Log4j是一个用java写的优秀日志软件包。它与众不同地特色之一是继承日志记录器概念。用用日志记录器层次,使按任意的粒度控制日志语句输出成为可能。这有助于减少日志输出量,并最小化日志消耗。

Log4j API的特色之一是它的易管理性。一旦日志语句被插入代码,他们可以用配置文件来控制。他们可以有选择的激活或不激活。Log4j包被设计以便于日志语句可以以漂码(in shipped code)的方式保存,而不会致使大量的性能消耗。 感谢

非常感谢N. Asokan审阅了这篇文章。他logger概念的创立者之一。感谢Nelson Minar鼓励我写这片文章。他也对这篇文章提出了许多有用的建议和修正。Log4j是集体努力的结果。谢谢所有对这个项目作出贡献的作者。毫无例外,在包中最好的特色已经在用户社群中广泛创建了。

/************************************************/ 下面中盛友成做的实例

/***********************************************/

一、建Web Project工程,将log4j-1.2.13.jar导入到WEB-INF\\lib下 二、建servlet,名称为:Log4jInit.java 内容如下:

/////////////////////////////////////////////////////////////// package com.sys86.log4j; import java.io.IOException;

import javax.servlet.ServletException; import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse; import org.apache.log4j.PropertyConfigurator; public class Log4jInit extends HttpServlet {

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { }

public void init() throws ServletException {

String prefix = getServletContext().getRealPath(\ String file = getInitParameter(\ if(file != null){

PropertyConfigurator.configure(prefix+file); } } }

//////////////////////////////////////////////////////

三、建TestBean.java类(可以自己随便写一下)

///////////////////////////////////////////////////// package com.sys86.test;

import org.apache.log4j.Logger; import org.apache.log4j.Priority; public class TestBean {

private static Logger logger = Logger.getLogger(TestBean.class); protected String title; public String getTitle() {

logger.debug(\这里是Log4j获得的信息\ return title; }

public void setTitle(String title) {

logger.info(\这里是Log4j获得的信息\ logger.debug(\

logger.info(\ logger.warn(\ logger.error(\ logger.fatal(\ logger.log(Priority.DEBUG, \ logger.debug(\ this.title = title; } }

////////////////////////////////////////////////////////////

四、在src下建log4j.properties文件,内容如下:下面只写了部分参数,全部的见详细说明 //////////////////////////////////////////////////////////// log4j.rootCategory=INFO,stdout,R

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n

log4j.appender.R=org.apache.log4j.DailyRollingFileAppender log4j.appender.R.File=C:\\\\SysTestLog4j.log

log4j.appender.R.layout=org.apache.log4j.PatternLayout

log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n

log4j.logger.com.neusoft=DEBUG

log4j.logger.com.opensymphony.oscache=ERROR log4j.logger.net.sf.navigator=ERROR log4j.logger.org.apache.commons=ERROR log4j.logger.org.apache.struts=WARN log4j.logger.org.displaytag=ERROR

log4j.logger.org.springframework=DEBUG log4j.logger.com.ibatis.db=WARN

log4j.logger.org.apache.velocity=FATAL

log4j.logger.com.canoo.webtest=WARN

log4j.logger.org.logicalcobwebs=WARN

///////////////////////////////////////////////////////////////

五、在web.xml中添加初始化参数,代码如下:

///////////////////////////////////////////////////////////////

xmlns=\

xmlns:xsi=\ xsi:schemaLocation=\ http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd\

Log4jInit

com.sys86.log4j.Log4jInit

log4j-init-file log4j.properties

1

index.jsp

//////////////////////////////////////////////////////////////

六、再加一个index.jsp调用测试吧。

///////////////////////////////////////////////////////////// <%@ page language=\

log4j示例
<%

testBean.setTitle(\我是从index.jsp中设定的值***\%>

///////////////////////////////////////////////////////////////

以前都是把所有日志都输出到一个文件下面,今天有个同事问想把某个包下的日志输出到指定的地方,于是就在网上查了一些资料,总结一下,以免以后用到。

一、log4j是什么?

Log4j是一个开源的日志记录组件,其产品已经相当的成熟,且使用非常的广泛。在工程中以易用,方便等代替了 System.out 等打印语句。

Log4j的目标是:它允许开发人员以任意的精细程度控制哪些日志说明被输出。通过使用外部的配置文件,可以在运行时配置它。

Log4j的具体在 http://logging.apache.org/log4j/找到它(有使用的文档说明)。另外,log4j已经被转换成 C, C++, C#, Perl, Python, Ruby, 和 Eiffel 语言。 二、通常我们建立一个log4j.properties文件放在src下,编译之后就生成在../web-inf/class/当然也可以放到其它任何目录,只要该目录被包含到类路径中即可,中定位这个文件,并读入这个文件完成的配置。这个配置文件告诉Log4J以什么样的格式、把什么样的信息、输出到什么地方。

Log4j有三个主要的组件:Loggers(记录器),Appenders(输出源)和Layouts(布局),这里可简单理解为日志类别,日志要输出的地方和日志以何种形式输出。综合使用这三个组件可以轻松的记录信息的类型和级别,并可以在运行时控制日志输出的样式和位置。下面对三个组件分别进行说明: 1、 Loggers

Loggers组件在此系统中被分为五个级别:DEBUG、INFO、WARN、ERROR和FATAL。这五个级别是有顺序的,DEBUG Log4j有一个规则:假设Loggers级别为P,如果在Loggers中发生了一个级别Q比P高,则可以启动,否则屏蔽掉。

假设你定义的级别是info,那么error和warn的日志可以显示而比他低的debug信息就不显示了。 其语法表示为:

org.apache.log4j.ConsoleAppender(控制台) org.apache.log4j.FileAppender(文件)

org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)

org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件) org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

配置时使用方式为:

log4j.appender.appenderName = fully.qualified.name.of.appender.class log4j.appender.appenderName.option1 = value1 ?

log4j.appender.appenderName.option = valueN 这样就为日志的输出提供了相当大的便利。

3、Layouts

有时用户希望根据自己的喜好格式化自己的日志输出。Log4j可以在Appenders的后面附加Layouts来完成这个功能。Layouts提供了四种日志输出样式,如根据HTML样式、自由指定样式、包含日志级别与信息的样式和包含日志时间、线程、类别等信息的样式等等。

其语法表示为:

org.apache.log4j.HTMLLayout(以HTML表格形式布局), org.apache.log4j.PatternLayout(可以灵活地指定布局模式),

org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),

org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

配置时使用方式为:

log4j.appender.appenderName.layout =fully.qualified.name.of.layout.class log4j.appender.appenderName.layout.option1 = value1 ?

log4j.appender.appenderName.layout.option = valueN 4 . Log4j的配置

以上是从原理方面说明Log4j的使用方法,在具体Java编程使用Log4j可以参照以下示例:

1、建立Logger实例:

语法表示:public static Logger getLogger( String name)

实际使用:static Logger logger = Logger.getLogger(ServerWithLog4j.class.getName ()) ;

2、读取配置文件:

获得了Logger的实例之后,接下来将配置Log4j使用环境: 语法表示:

或者直接放在src下把log4j.properties文件

BasicConfigurator.configure():自动快速地使用缺省Log4j环境。

PropertyConfigurator.configure(String configFilename):读取使用Java的特性文件编写的配置文件。 DOMConfigurator.configure(String filename):读取XML形式的配置文件。 实际使用:

PropertyConfigurator.configure(\

3、插入日志信息

完成了以上连个步骤以后,下面就可以按日志的不同级别插入到你要记录日志的任何地方了。 语法表示:

Logger.debug(Object message);//调试信息 Logger.info(Object message);//一般信息 Logger.warn(Object message);//警告信息 Logger.error(Object message);//错误信息 Logger.fatal(Object message);//致命错误信息

实际使用:logger.info(\

5. 配置过程 Log4j真正在系统中运行事先还要对配置文件进行定义。定义步骤就是对Logger、Appender及Layout的分别使用。

Log4j支持两种配置文件格式,一种是XML格式的文件,一种是java properties(key=value)【Java特性文件(键=值)】。下面我们介绍使用Java特性文件做为配置文件的方法 具体如下:

三、配置根Logger,其语法为:

log4j.rootLogger = [ level ] , appenderName1, appenderName2, …

level : 是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来。

appenderName:就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。 例如:log4j.rootLogger=info,A1,B2,C3

2、配置日志信息输出目的地,其语法为:

log4j.appender.appenderName = fully.qualified.name.of.appender.class //

\可以指定下面五个目的地中的一个: 1.org.apache.log4j.ConsoleAppender(控制台) 2.org.apache.log4j.FileAppender(文件)

3.org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)

4.org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件) 5.org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方) 1.ConsoleAppender选项

Threshold=WARN:指定日志消息的输出最低层次。

ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。 Target=System.err:默认情况下是:System.out,指定输出控制台 2.FileAppender 选项

Threshold=WARN:指定日志消息的输出最低层次。

ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。 File=mylog.txt:指定消息输出到mylog.txt文件。

Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。 3.DailyRollingFileAppender 选项

Threshold=WARN:指定日志消息的输出最低层次。

ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。

File=mylog.txt:指定消息输出到mylog.txt文件。

Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。

DatePattern='.'yyyy-ww:每周滚动一次文件,即每周产生一个新的文件。当然也可以指定按月、周、天、时和分。即对应的格式如下: 1)'.'yyyy-MM: 每月 2)'.'yyyy-ww: 每周 3)'.'yyyy-MM-dd: 每天

4)'.'yyyy-MM-dd-a: 每天两次 5)'.'yyyy-MM-dd-HH: 每小时 6)'.'yyyy-MM-dd-HH-mm: 每分钟 4.RollingFileAppender 选项

Threshold=WARN:指定日志消息的输出最低层次。

ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。 File=mylog.txt:指定消息输出到mylog.txt文件。

Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。

MaxFileSize=100KB: 后缀可以是KB, MB 或者是 GB. 在日志文件到达该大小时,将会自动滚动,即将原来的内容移到mylog.log.1文件。

MaxBackupIndex=2:指定可以产生的滚动文件的最大数。 实际应用:

log4j.appender.A1=org.apache.log4j.ConsoleAppender //这里指定了日志输出的第一个位置A1是控制台ConsoleAppender

3、配置日志信息的格式,其语法为:

A. log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class \可以指定下面4个格式中的一个: 1.org.apache.log4j.HTMLLayout(以HTML表格形式布局),

2.org.apache.log4j.PatternLayout(可以灵活地指定布局模式),

3.org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),

4.org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息) 1.HTMLLayout 选项

LocationInfo=true:默认值是false,输出java文件名称和行号 Title=my app file: 默认值是 Log4J Log Messages. 2.PatternLayout 选项

ConversionPattern=%m%n :指定怎样格式化指定的消息。 3.XMLLayout 选项

LocationInfo=true:默认值是false,输出java文件和行号 实际应用:

log4j.appender.A1.layout=org.apache.log4j.PatternLayout

B. log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %d{yyyy-MM-dd HH:mm:ssS} %c %m%n 这里需要说明的就是日志信息格式中几个符号所代表的含义: -X号: X信息输出时左对齐;

%p: 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL,

%d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921 %r: 输出自应用启动到输出该log信息耗费的毫秒数 %c: 输出日志信息所属的类目,通常就是所在类的全名 %t: 输出产生该日志事件的线程名 %l: 输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)

%x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。 %%: 输出一个\字符

%F: 输出日志消息产生时所在的文件名称 %L: 输出代码中的行号

%m: 输出代码中指定的消息,产生的日志具体信息

%n: 输出一个回车换行符,Windows平台为\,Unix平台为\输出日志信息换行

可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如:

1) c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,默认的情况下右对齐。 2)%-20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,\号指定左对齐。

3)%.30c:指定输出category的名称,最大的宽度是30,如果category的名称大于30的话,就会将左边多出的字符截掉,但小于30的话也不会有空格。

4) .30c:如果category的名称小于20就补空格,并且右对齐,如果其名称长于30字符,就从左边交远销出的字符截掉。

这里上面三个步骤是对前面Log4j组件说明的一个简化;下面给出一个具体配置例子,在程序中可以参照执行: log4j.rootLogger=INFO,A1,B2

log4j.appender.A1=org.apache.log4j.ConsoleAppender log4j.appender.A1.layout=org.apache.log4j.PatternLayout

log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %d{yyyy-MM-dd HH:mm:ssS} %c %m%n

根据上面的日志格式,某一个程序的输出结果如下: 0 INFO 2003-06-13 13:23:46968 ClientWithLog4j Client socket: Socket[addr=localhost/127.0.0.1,port=8002,localport=2014]

16 DEBUG 2003-06-13 13:23:46984 ClientWithLog4j Server says: 'Java server with log4j, Fri Jun 13 13:23:46 CST 2003' 16 DEBUG 2003-06-13 13:23:46984 ClientWithLog4j GOOD

16 DEBUG 2003-06-13 13:23:46984 ClientWithLog4j Server responds: 'Command 'HELLO' not understood.' 16 DEBUG 2003-06-13 13:23:46984 ClientWithLog4j HELP

16 DEBUG 2003-06-13 13:23:46984 ClientWithLog4j Server responds: 'Vocabulary: HELP QUIT' 16 DEBUG 2003-06-13 13:23:46984 ClientWithLog4j QUIT

4. # 当输出信息于回滚文件时

log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender //指定以文件的方式输出日志 log4j.appender.ROLLING_FILE.Threshold=ERROR

log4j.appender.ROLLING_FILE.File=rolling.log //文件位置,也可以用变量${java.home}、rolling.log log4j.appender.ROLLING_FILE.Append=true

log4j.appender.ROLLING_FILE.MaxFileSize=10KB //文件最大尺寸 log4j.appender.ROLLING_FILE.MaxBackupIndex=1 //备份数

log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout

log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

四、具体应用文件配置举例

#所有包下的日志信息都输出到下面的日志路径下 log4j.rootLogger=INFO,trycatch

log4j.appender.trycatch=org.apache.log4j.RollingFileAppender log4j.appender.trycatch.File=d:/loginfo/trycatch.log log4j.appender.trycatch.MaxFileSize=500KB log4j.appender.trycatch.MaxBackupIndex=1

log4j.appender.trycatch.layout=org.apache.log4j.PatternLayout

log4j.appender.trycatch.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c] [%p] - %m%n #指定目录下包下的日志信息都存放到该目录下 log4j.logger.cn.com.cuigq.Theard=DEBUG,R1

log4j.appender.R1=org.apache.log4j.RollingFileAppender

log4j.appender.R1.File=d:/loginfo/iamSystem1.log log4j.appender.R1.MaxFileSize=500KB log4j.appender.R1.MaxBackupIndex=1

log4j.appender.R1.layout=org.apache.log4j.PatternLayout

log4j.appender.R1.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c] [%p] - %m%n #指定目录下的java类的日志信息都存放到该目录下 log4j.logger.com.cuigq.TestError=DEBUG,R2

log4j.appender.R2=org.apache.log4j.DailyRollingFileAppender log4j.appender.R2.File=d:/loginfo/html.html #log4j.appender.R2.MaxFileSize=500KB #log4j.appender.R2.MaxBackupIndex=1

log4j.appender.R2.layout=org.apache.log4j.HTMLLayout

#log4j.appender.R2.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c] [%p] - %m%n #指定目录下包下的日志信息都存放到数据库 log4j.logger.database=DEBUG,oracledb

log4j.appender.oracledb=org.apache.log4j.jdbc.JDBCAppender log4j.appender.oracledb.Driver=oracle.jdbc.driver.OracleDriver

log4j.appender.oracledb.URL=jdbc:oracle:thin:@192.168.20.92:1521:chshsid(切忌此处为sid而不是数据库名) log4j.appender.oracledb.user=scott log4j.appender.oracledb.password=tiger #log4j.appender.encoding=utf-8

log4j.appender.oracledb.sql=INSERT INTO enter_ora_log4j VALUES ('%d{yyyy-MM-dd HH:mm:ss}', '%t', '%p', '%l', '%m') log4j.appender.oracledb.layout=org.apache.log4j.PatternLayout

第一部分 快速入门

首先,需要去下载LOG4J这个软件并解压缩出其中的log4j.jar.在你的应用程序的classpath中包含该JAR文件,你也可以简单地将这个文件拷贝到JDK的%java_home%\\lib\\ext目录下。在作完以上工作后,你可以将下面的代码保存到名为TestLogging.java中:############################## import org.apache.log4j.*; // How to use log4j public class TestLogging {

// Initialize a logging category. Here, we get THE ROOT CATEGORY //static Category cat = Category.getRoot(); // Or, get a custom category

static Category cat = Category.getInstance(TestLogging.class.getName()); // From here on, log away! Methods are: cat.debug(your_message_string),

// cat.info(...), cat.warn(...), cat.error(...), cat.fatal(...) public static void main(String args[]) { // Try a few logging methods cat.debug(\

cat.info(\ cat.warn(\ cat.error(\ cat.fatal(\ // Alternate but INCONVENIENT form cat.log(Priority.DEBUG, \ new TestLogging().init(); }

public void init() {

java.util.Properties prop = System.getProperties(); java.util.Enumeration enum = prop.propertyNames(); cat.info(\ cat.debug(\ while (enum.hasMoreElements()) {

String key = (String) enum.nextElement(); cat.info(key + \ } } }

############################################################ Log4J 默认情况下可以记录五个层次(由低到高)的日志消息。 1)debug 2)info 3)warn 4)error 5)fatal

在TestLoggin.class的目录中保存下列行在一个名字为log4j.properties 文件中.默认情况下,当你在代码中使用getRoot()或getInstance(\时,Log4j会在应用程序的classpath中查找该文件: ############################################ log4j.rootCategory=DEBUG, dest1

log4j.appender.dest1=org.apache.log4j.ConsoleAppender log4j.appender.dest1.layout=org.apache.log4j.PatternLayout ############################################

ConsoleAppender指定的是控制台附加器,即日志消息会输出到控制台上,而PatternLayout则指定了消息输出的格式,默认情况下格式为%m%n,%m指定的是消息内容,%n指定的是操作系统平台上的换行符,这里更类似于C语言中的输出控制语句。 现在,你可以编译并且运行TestLogging.java了,你可以获得以下输出结果: Start of main()

Just testing a log message with priority set to INFO Just testing a log message with priority set to WARN Just testing a log message with priority set to ERROR Just testing a log message with priority set to FATAL Calling init()

***System Environment As Seen By Java*** ***Format: PROPERTY = VALUE***

java.runtime.name = Java(TM) 2 Runtime Environment, Standard Edition sun.boot.library.path = c:\\jdk1.3\\jre\\bin java.vm.version = 1.3.0_02

java.vm.vendor = Sun Microsystems Inc. ... and so on

如果想打印消息的层次如debug,info,error等,那可以在log4j.properties 文件的最后一行上增加如下一行: log4j.appender.dest1.layout.ConversionPattern=%-5p: %m%n

这一行覆盖了默认的消息输出格式%m%n,%p指定的是打印消息的层次(info,debug...,其中-5指定的是五个字符的宽度,-指定的是左对齐),%m指定的是消息的内容,%n指定的则是操作系统平台上的换行符.

当作完这些工作后,无须重新编译TestLogging.java,再次运用TestLogg,会得到以下不出的输出结果: DEBUG: Start of main()

INFO : Just testing a log message with priority set to INFO WARN : Just testing a log message with priority set to WARN ERROR: Just testing a log message with priority set to ERROR FATAL: Just testing a log message with priority set to FATAL DEBUG: Calling init()

INFO : ***System Environment As Seen By Java*** DEBUG: ***Format: PROPERTY = VALUE***

INFO : java.runtime.name = Java(TM) 2 Runtime Environment, Standard Edition INFO : sun.boot.library.path = c:\\jdk1.3\\jre\\bin INFO : java.vm.version = 1.3.0_02

INFO : java.vm.vendor = Sun Microsystems Inc. ... and so on

如果不想输出日志的DEBUG与INFO消息,那么可以修改\为: log4j.rootCategory=WARN,dest1

该行文件告诉Log4j跳过层次低于WARN的消息输出,也就是说如DEBUG,INFO层次的消息将不会产生输出,再次运行TestLogging.class,得到以下结果: ####################

WARN : Just testing a log message with priority set to WARN ERROR: Just testing a log message with priority set to ERROR FATAL: Just testing a log message with priority set to FATAL ####################

第二部分 Log4j 详解

Log4j有三个主要的组件:category ,附件器和布局。

在程序中,你可以初始化一个category 并且调用它的各种日志方法来将消息字符串记录到日志中。

一个category可以被配置用来输出到多个目标,这些日志目标在Log4j框架中被称为附件器,这些附件器可以包括控制台、文本文件、HTML文件、XML文件甚至是Windows平的事件日志系统,甚至可以被作为邮件被发送。而这些所有的目标都是通过log4j.properties文件来进行配置,对于使用Log4j框架的程序来讲只是简单地调用类似于info()、debug()等的方法。 附件器类可以是

ConsoleAppender, FileAppender, SMTPAppender, SocketAppender, NTEventLogAppender,

SyslogAppender, JMSAppender, AsyncAppender 和 NullAppender等。 附件器类可以使用布局(layout)来在发送消息到目标之前进行格式化。例如HTMLLayout将会把消息格式化为HTML 格式。

除了可以记录消息字符串到日志文件之外,同时还可以记录日期、时间、消息层次、类名、源代码的行数、方法名称、线程名称以及其它信息,而具体的输出需要由附件器的布局管理器来配置。

category的名字是大小写区分以\分隔的一个字符串。一般情况下我们通常使用your_class_name.class.getName()来获得一个JAVA类名来作为category的名字,例如testproj.util.test。

Each word in the category name is said to be an ancestor of the subsequent words and a parent of the immediately following word. This is important because Log4j has this concept of inheriting priorities and appenders from ancestors until overridden in a particular category.

有一个没有名称的category叫root,它就像xml的document元素,是所有category的祖先。 可以使用以下代码来初始一个根category或指定的category。 ################

Category cat = Category.getRoot();

Category cat2 = Category.getInstance(\###################

代表层次的常量由高到次是FATAL、ERROR、WARN、INFO和DEBUG,可以在log4j.properties中指定category所属的层次,例如指定log4j.rootCategory=WARN,simple则意味调用root这个category的程序只会记录WARN及WARN以上的消息。如果没有为一个category指定默认的category,那么category将会从其父category来继承。 常见的Category类的日志方法有:

public void log(Priority p, Object message);

// Convenient shortcuts to the generic logging method public void debug(Object message); public void info(Object message); public void warn(Object message); public void error(Object message);

public void fatal(Object message);

log4j 只记录层次与预设层次相等或更高级别的消息,如以下代码: Category cat = Category.getRoot();

cat.setPriority(Priority.ERROR);//设置预设层次为ERROR级 // Later...

//cat.info(\这条消息将不会输出,ERROR cat.error(\消息输出,层次相等

cat.fatal(\消息输出,层次高于预设层次

第三部分 Log4j 配置

所有的配置工作应该在log4j.properties文件中完成,而该文件一般须放在应用程序的相同的目录中。

在日志系统使用之前,我们必须首先配置log4j.配置log4j意味着增加附件器到Category并且为每一个Category设置一个Layout。

category之间是有继承关系,但他们增加到log4j.properties文件中的顺序是不固定的。 示例一:

#############################################################

# 设置log4j的根category所使用的预设层次是DEBUG,而只使用A1这个附件器. log4j.rootCategory=DEBUG, A1 #附件器A1被设置为控制台附件器。

log4j.appender.A1=org.apache.log4j.ConsoleAppender #附件器使用的布局是PatternLayout,即模式布局

log4j.appender.A1.layout=org.apache.log4j.PatternLayout

#附件器A1的模式是%-4r [%t] %-5p %c %x - %m%n,其中%m代表消息字符串,%n代表换行符,其它以%开头的字符代表的含义如下文。

log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n ################################################################# 示例二:

#########################################################

#### Use two appenders, one to log to console, another to log to a file log4j.rootCategory=debug, stdout, R

# Print only messages of priority WARN or higher for your category log4j.category.your.category.name=WARN # Specifically inherit the priority level #log4j.category.your.category.name=INHERITED #### First appender writes to console

log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout # Pattern to output the caller's file name and line number.

log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

#### Second appender writes to a file

log4j.appender.R=org.apache.log4j.RollingFileAppender log4j.appender.R.File=example.log # Control the maximum log file size log4j.appender.R.MaxFileSize=100KB # Archive log files (one backup file here) log4j.appender.R.MaxBackupIndex=1

log4j.appender.R.layout=org.apache.log4j.PatternLayout log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n ########################################################

第四部分 Log4j中有用的Layout

一些有用的layout有TTCCLayout, HTMLLayout, PatternLayout, SimpleLayout 和 XMLLayout.

其中SimpleLayout和PatternLayout忽略JAVA throwable 接口派生出来的errors和Exceptions.HTMLLayout和XMLLayout处理这些异常。

SimpleLayout的输出中包含日志消息的层次,紧跟着“-”后面的日志消息字符串。例如: DEBUG - Hello World Message

Patternlayout 可以根据输出的模式字符串来决定消息的输出,模式字符串类似于C语言中的模式字符串。例如PatternLayout中如果使用模式字符串“%r [%t] %-5p %c -%m%n”会输出以下消息: 176 [main] INFO org.foo.Bar -Located nearest gas station 以下对各域作一下解释:

1)%r输出程序开始执行之后的微秒数 2)%t输出当前线程的名称 3)%-5p输出消息的层次。 4)%c 输出category的名称

5)-%m及s是日志消息本身,%n是换行符。

当前在模式字符串中你可以嵌入任何想要输出的字符。 模式字符串中的模式如下: %m:消息本身 %p:消息的层次

%r:从程序开始执行到当前日志产生时的时间间隔(微秒)

%c:输出当前日志动作所在的category名称。例如:如果category名称是\将会输出\{2}意谓着输出“以点分隔开的category名称的后两个组件”,如果 {n}没有,将会输出整个category名称. %t:输出当前线程的名称

%x:输出和当前线程相关联的NDC(具体解释见下文),尤其用到像java servlets这样的多客户多线程的应用中。 %n:输出平台相关的换行符。 %%:输出一个\字符

%d:输出日志产生时候的日期,当然可以对日期的格式进行定制。例如:%d{HH:mm:ss,SSSS}或者是%d{dd MMM yyyy HH:mm:ss,SSSS},如果没有指定后面的格式,将会输出ISO8601的格式。 %l:输出位置信息,相当于%C.%M(%F:%L)的组合。

%C:输出日志消息产生时所在的类名,如果类名是“test.page.Class1”%C{1}表示输出类名\输出\而%C则输出\。 %M:输出日志消息产生时的方法名称 %F:输出日志消息产生时所在的文件名称 %L:输出代码中的行号

可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如:

1) c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,默认的情况下右对齐。 2) %-20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,\号指定左对齐。 3) %.30c:指定输出category的名称,最大的宽度是30,如果category的名称大于30的话,就会将左边多出的字符截掉,但小于30的话也不会有空格。

4) .30c:如果category的名称小于20就补空格,并且右对齐,如果其名称长于30字符,就从左边交远销出的字符截掉。 4) .30c:

第五部分 Log4j中附件器及相关的键值参数

1.ConsoleAppender选项

Threshold=WARN:指定日志消息的输出最低层次。

ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。 Target=System.err:默认情况下是:System.out,指定输出控制台 2.FileAppender 选项

Threshold=WARN:指定日志消息的输出最低层次。

ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。 File=mylog.txt:指定消息输出到mylog.txt文件。

Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。 3.RollingFileAppender 选项

Threshold=WARN:指定日志消息的输出最低层次。

ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。 File=mylog.txt:指定消息输出到mylog.txt文件。

Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。

MaxFileSize=100KB: 后缀可以是KB, MB 或者是 GB. 在日志文件到达该大小时,将会自动滚动,即将原来的内容移到mylog.log.1文件。

MaxBackupIndex=2:指定可以产生的滚动文件的最大数。 4.DailyRollingFileAppender 选项

Threshold=WARN:指定日志消息的输出最低层次。

ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。 File=mylog.txt:指定消息输出到mylog.txt文件。

Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。

DatePattern='.'yyyy-ww:每周滚动一次文件,即每周产生一个新的文件。当然也可以指定按月、周、天、时和分。即对应的格式如下:

Log4J是Apache的一个开放源代码项目(http://logging.apache.org/log4j/docs/),它是一个日志操作包。通过使用Log4J,可以指定日志信息输出的目的地,控制每一条日志的输出格式,定义日志信息的级别。所有这些功能通过一个配置文件灵活进行配置。

一、LOG4J组成

LOG4J主要由三大组件组成:

. Logger: 决定什么日志信息应该被输出、什么日志信息应该被忽略;

. Appender: 指定日志信息应该输出到什么地方, 这些地方可以是控制台、文件、网络设备; . Layout: 指定日志信息的输出格式;

一个Logger可以有多个Appender,也就是说日志信息可以同时输出到多个设备上,每个Appender对应 一种Layout(示例见下图)。 ↗ Appender1 → Layout / Logger ﹨

↘ Appender2 → Layout

二、Logger组件

1. Logger组件提供的方法:

Logger组件是LOG4J的核心组件,它代表了Log4J的日志记录器,它能够对日志信息进行分类筛选。它由org.apache.log4j.Logger类实现,提供了如下方法:

java 代码

package org.apache.log4j;

public class Logger {

// Creation & retrieval methods: public static Logger getRootLogger(); public static Logger getLogger(String name);

// printing methods:

public void debug(Object message); public void info(Object message); public void warn(Object message); public void error(Object message); public void fatal(Object message);

// generic printing method:

public void log(Priority p, Object message); }

2. 在配置文件中配置Logger组件

可在Log4J配置文件中配置自己的Logger组件,示例: log4j.logger.myLogger=WARN

以上代码定义了一个Logger组件,名称为myLogger,日志级别为WARN。

3. 日志级别种类:

一共有五种,级别由高到低依次是:fatal、error、warn、info、debug。获得Logger实例后,我们可调用以下方法之一输出日志信息:

public void debug(Object message); //输出debug级别的日志信息; public void info(Object message); //输出info级别的日志信息; public void warn(Object message); //输出warn级别的日志信息; public void error(Object message); //输出error级别的日志信息; public void fatal(Object message); //输出fatal级别的日志信息;

public void log(Priority p, Object message);//输出参数Priority指定级别的日志信息;

以上方法只有当它的级别大于或等于Logger组件配置的日志级别时才调用。以前面我们配置的myLogger为例,它的日志级别为WARN, 那么在程序中,它的warn()、error()、fatal()方法会被执行。对于log()方法,只有当它的参数Priority指定的日志级别大于或等于WARN时,它才会被执行。

4. 为什么需要对日志进行分级?

在写程序的时候,为了调试程序,我们会在很多出错的地方输出大量的日志信息。当程序调试完,不需要这些信息时,将程序中这些输出日志信息代码删除吗?这样费时费力,对于大型程序几乎不可行。通过对日志分级,假如不想输出WARN级别的日志信息,则Logger组件的级别调高即可,省时省心。

5. Logger组件的继承性

Log4J提供了一个root Logger,它是所有Logger组件的“祖先”,它永远存在,且不能通过名字检索或引用,通过Logger.getRootLogger()方法取得它。配置root Logger代码: log4j.rootLogger=INFO,console

可在配置文件中方便地配置存在继承关系的Logger组件,凡是在符号“.”后面的组件都会成为在符号“.”前面的Logger组件的子类。例如:

log4j.apache.myLogger=WARN

log4j.apache.myLogger.mySonLogger=,file

以上代码中, mySonLogger是myLogger的子类Logger组件。

Logger组件的继承关系:

. 如果子类Logger组件没有定义日志级别,则将继承父类的日志级别; . 如果子类Logger组件定义了日志级别,就不会继承父类的日志级别;

. 黙认情况下,子类Logger组件会继承父类所有的Appender,把它们加入到自己的Appener;

. 如果把子类Logger组件的additivity标志设为false,那么它就不会继承父类Appender。additivity标志 默认值为false; 以上配置的三个Logger继承关系示例如图:

root Logger: 日志级别=INFO appender清单=console ↑

myLogger: 日志级别=WARN appender清单=null ↑

mySonLogger: 日志级别=null appender清单=file 这三个Logger组件实际日志级别和Appender如下表: Logger组件 日志级别 Appender清单 root Logger INFO console myLogger WARN console(继承)

mySonLogger WARN(继承) file,console(继承)

三、Appender组件

Appender组件决定将日志信息输出到什么地方。支持以下目的地: . 控制台(Console); . 文件(File);

. GUI组件(GUI component);

. 套接口服务器(Remote socket server); . NT的事件记录器(NT Event Logger);

. UNIX Syslog守护进程(Remote UNIX Syslog daemon);

一个Logger可同时对应多个Appender,示例:myLogger配置二个Appender: 一个file, 一个是console: log4j.logger.myAppender=WARN,file,console

log4j.appender.file=org.apache.log4j.RollingFileAppender log4j.appender.file.File=log.txt

log4j.apender.console=org.apache.log4j.ConsoleAppender

四、Layout组件

Layout组件决定日志输出格式,有以下几种类型: . org.apache.log4j.HTMLLayout(以HTML表格形式布局); . org.apache.log4j.PatternLayout(可以灵活地指定布局模式); . org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串); . org.apache.log4j.TTCCLayout(包含日志产生的时间、线程和类别等信息);

为名称为console的Appender配置SimpleLayout,代码如下: log4j.appender.console.layout=org.apache.log4j.SimpleLayout 输出日志格式如下:

WARN - This is a log message from the myLogger

为名称为file的Appender配置PatternLayout,代码如下: log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%t %p - %m%n 输出日志格式如下:

THREAD-1 WARN - This is a log message from the myLogger

PatternLayout让开发者依照ConversionPattern定义输出格式。ConversionPattern中一些指定日志内容和格式的预定义符号说明如下:

符号 描述

%r 自程序开始后消耗的毫秒数 %t 表示日志记录请求生成的线程 %p 表示日专语句的优先级 %r 与日志请求相关的类别名称 %c 日志信息所在的类名 %m%n 表示日志信息的内容

五、Log4J的基本用法

1. 定义配置文件

Log4J支持二种配置文件格式:XML和Java属性文件(采用“键=值”形式)。以下为Java属性文件 格式配置文件:

. 配置Logger组件

配置root Logger语法为:log4j.rootLogger=[priority],appenderName,appenderName,... 配置自定义Logger组件语法为:log4j.logger.loggerName=[priority],appenderName,appenderName,? 其中:priority为日志级别,可选值包括FATAL、ERROR、WARN、INFO、DEBUG、ALL; appenderName指定Appender组件,可指定多个;

. 配置Appender组件

配置日志信息输出目的地Appender, 语法为:

log4j.appender.appenderName=fully.ualified.name.of.appender.class

log4j.appender.appenderName.option1=value1 ...

log4j.appender.appenderName.optionN=valueN Log4J提供的Appender有以下几种:

a. org.apache.log4j.ConsoleAppender(控制台); b. org.apache.log4j.FileAppender(文件);

c. org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件);

d. org.apache.log4j.RollingFileAppender(文件大小到指定尺寸产生一个新的文件); e. org.apache.log4j.WriteAppender(将日志信息以流格式发送到任意指定地方);

. 配置Layout组件

配置Layout组件语法为:

log4j.appender.appenderName.layout=fully.ualified.name.of.appender.class log4j.appender.appenderName.layout.option1=value1 ...

log4j.appender.appenderName.layout.optionN=valueN 下面为一配置文件示例,文件名为log4j.properties: ## LOGGERS ##

#configure root logger log4j.rootLogger=INFO,console #define a logger named myLogger log4j.logger.myLogger=WARN

#define a second logger that is a child to myLogger log4j.logger.myLogger.mySonLogger=,file ## APPENDERS ##

#define an appender named console, which is set to be a ConsoleAppender log4j.appender.console=org.apache.log4j.ConsoleAppender

# define an appender named file, which is set to be a RollingFileAppender log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.File=log.txt ## LAYOUTS ##

# assian a SimpleLayout to console appender

log4j.appender.console.layout=org.apache.log4j.SimpleLayout # assian a PatternLayout to file appender

log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%t%p-%m%n

2. 程序中使用Log4j

. 获得日志记录器:

获得rootLogger:Logger rootLogger=Logger.getRootLogger();

获得自定义Logger:Logger myLogger = Logger.getLogger(\

. 读取日志记录器,配置Log4J环境;

a. BasicConfigurator.configure(): 自动快速地使用默认Log4J环境;

b. PropertyConfigurator.configure(String configFilename): 读取使用Java属性格式的配置文件并配置Log4J环境; c. DOMConfigurator.configure(String filename): 读取XML形式的配置文件并配置LOG4J环境;

. 输出日志信息;

在程序代码中需要生成日志的地方,调用Logger的各种输出日志方法输出不同级别的日志,例如: myLogger.debug(\ 下面为一使用Log4J的程序,程序名为Test.java: //java 代码

import org.apache.log4j.Logger;

import org.apache.log4j.PropertyConfigurator;

public class Test {

public static void main(String[] args) { //Get an instance of the myLogger

Logger myLogger = Logger.getLogger(\

//Get an instance of the childLogger

Logger mySonLogger = Logger.getLogger(\ //Load the proerties using the PropertyConfigurator PropertyConfigurator.configure(\

//Log Messages using the Parent Logger

myLogger.debug(\ myLogger.info(\ myLogger.warn(\ myLogger.error(\ myLogger.fatal(\

mySonLogger.debug(\ mySonLogger.info(\ mySonLogger.warn(\ mySonLogger.error(\ mySonLogger.fatal(\ } }

程序运行结果为:

WARN - Thie is a log message from the myLogger ERROR - Thie is a log message from the myLogger FATAL - Thie is a log message from the myLogger

WARN - Thie is a log message from the myLogger.mySonLogger ERROR - Thie is a log message from the myLogger.mySonLogger FATAL - Thie is a log message from the myLogger.mySonLogger 另在Test.class所在的目录下看到一个log.txt文件,内容如下: WARN - Thie is a log message from the myLogger.mySonLogger ERROR - Thie is a log message from the myLogger.mySonLogger FATAL - Thie is a log message from the myLogger.mySonLogger 如将配置文件log4j.properties中语句 log4j.logger.myLogger.mySonLogger=,file 改为

log4j.logger.myLogger.mySonLogger=,file,console 再次运行程序,结果如下:

WARN - Thie is a log message from the myLogger ERROR - Thie is a log message from the myLogger FATAL - Thie is a log message from the myLogger

WARN - Thie is a log message from the myLogger.mySonLogger WARN - Thie is a log message from the myLogger.mySonLogger ERROR - Thie is a log message from the myLogger.mySonLogger

ERROR - Thie is a log message from the myLogger.mySonLogger FATAL - Thie is a log message from the myLogger.mySonLogger FATAL - Thie is a log message from the myLogger.mySonLogger

mySonLogger的日志在控制台上输出了二次,这是因为mySonLogger继承了父类console Appender, 本身又定义了一个console Appender, 因而有二个console Appender。

六、在web应用中使用Log4J

创建一个Servlet,在它初始化方法中读取Log4J配置文件并配置Log4J环境,这个Servlet在Web应用启 动时候被加载和初始化,然后就可在其它Web组件中获取Logger对象并输出日志。 1. 创建用于配置Log4J环境的Servlet //java 代码

import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.util.*;

import org.apache.log4j.PropertyConfigurator;

public class Log4JServlet extends HttpServlet { public void init() throws ServletException {

String path = getServletContext().getRealPath(\

//getInitParameter(\方法从web.xml文件中读取Log4J配置文件的名字\。 String propfile = path + getInitParameter(\ PropertyConfigurator.configure(propfile); } }

该Servlet在web.xml中的配置如下: //xml 代码

log4jServlet Log4JServlet

propfile

/WEB-INF/log4j.properties

1

2. 在login.jsp中输出日志

<[url=mailto:%@page]%@page import=\

login <%

Logger myLogger = Logger.getLogger(\

Logger mySonLogger = Logger.getLogger(\

myLogger.debug(\ myLogger.info(\

myLogger.warn(\ myLogger.error(\ myLogger.fatal(\ mySonLogger.debug(\ mySonLogger.info(\ mySonLogger.warn(\ mySonLogger.error(\ mySonLogger.fatal(\ %>

3. 发布运行使用Log4J的web应用

1) 将Log4J的JAR文件拷贝至目录:/WEB-INF/lib

2) 创建Log4J的配置文件log4j.properties, 存放目录为:/WEB-INF。内容同前面配置文件示例。 3) 编译Log4JServlet, 存放至目录: /WEB-INF/classes 4) 修改web.xml文件,加入以下内容: // xml 代码

log4jServlet Log4JServlet

profile

/WEB-INF/log4j.properties

1

5) 启动服务器,访问login.jsp页面,在服务器控制台上看到如下日志: WARN - Thie is a log message from the myLogger ERROR - Thie is a log message from the myLogger FATAL - Thie is a log message from the myLogger

WARN - Thie is a log message from the myLogger.mySonLogger ERROR - Thie is a log message from the myLogger.mySonLogger FATAL - Thie is a log message from the myLogger.mySonLogger

另在/WEB-INF目录下看到一个log.txt文件,内容如下: WARN - Thie is a log message from the myLogger.mySonLogger ERROR - Thie is a log message from the myLogger.mySonLogger FATAL - Thie is a log message from the myLogger.mySonLogger

log4j与log4j.properties的配置说明 2007-12-01 18:42 标签: java|log

在强调可重用组件开发的今天,除了自己从头到尾开发一个可重用的日志操作类外,Apache为我们提供了一个强有力的日志操作包-Log4j。

Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

此外,通过Log4j其他语言接口,您可以在C、C++、.Net、PL/SQL程序中使用Log4j,其语法和用法与在Java程序中一样,使得多语言 分布式系统得到一个统一一致的日志组件模块。而且,通过使用各种第三方扩展,您可以很方便地将Log4j集成到J2EE、JINI甚至是SNMP应用中。

说明:下面分为三部分,第一部分讲解如何配置log4j,第二部分为对log4j.properties配置文件中的各个属性的讲解,第三部分为对 log4j的详细讲解,如果只想配置上log4j,那么只需要看前两个部分就可以,如果想对log4j深入了解,则还需看第三部分。

一、Log4j配置

第一步:加入log4j-1.2.8.jar到lib下。

第二步:在CLASSPATH下建立log4j.properties。内容如下:

1 log4j.rootCategory=INFO, stdout , R 2

3 log4j.appender.stdout=org.apache.log4j.ConsoleAppender

4 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

5 log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n 6

7 log4j.appender.R=org.apache.log4j.DailyRollingFileAppender

8 log4j.appender.R.File=D:\\Tomcat 5.5\\logs\\qc.log

9 log4j.appender.R.layout=org.apache.log4j.PatternLayout

10 log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n

11

12 log4j.logger.com.neusoft=DEBUG

13 log4j.logger.com.opensymphony.oscache=ERROR

14 log4j.logger.net.sf.navigator=ERROR

15 log4j.logger.org.apache.commons=ERROR

16 log4j.logger.org.apache.struts=WARN

17 log4j.logger.org.displaytag=ERROR

18 log4j.logger.org.springframework=DEBUG

19 log4j.logger.com.ibatis.db=WARN

20 log4j.logger.org.apache.velocity=FATAL 21

22 log4j.logger.com.canoo.webtest=WARN 23

24 log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN

25 log4j.logger.org.hibernate=DEBUG

26 log4j.logger.org.logicalcobwebs=WARN

第三步:相应的修改其中属性,修改之前就必须知道这些都是干什么的,在第二部分讲解。

第四步:在要输出日志的类中加入相关语句:

定义属性:protected final Log log = LogFactory.getLog(getClass());

在相应的方法中:

if (log.isDebugEnabled()) {

log.debug(“System ?..”); }

二、Log4j说明

1 log4j.rootCategory=INFO, stdout , R

此句为将等级为INFO的日志信息输出到stdout和R这两个目的地,stdout和R的定义在下面的代码,可以任意起名。等级可分为OFF、 FATAL、ERROR、WARN、INFO、DEBUG、ALL,如果配置OFF则不打出任何信息,如果配置为INFO这样只显示INFO, WARN, ERROR的log信息,而DEBUG信息不会被显示,具体讲解可参照第三部分定义配置文件中的logger。

3 log4j.appender.stdout=org.apache.log4j.ConsoleAppender

此句为定义名为stdout的输出端是哪种类型,可以是

org.apache.log4j.ConsoleAppender(控制台),

org.apache.log4j.FileAppender(文件),

org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),

org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)

org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

具体讲解可参照第三部分定义配置文件中的Appender。

4 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

此句为定义名为stdout的输出端的layout是哪种类型,可以是

org.apache.log4j.HTMLLayout(以HTML表格形式布局),

org.apache.log4j.PatternLayout(可以灵活地指定布局模式),

org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),

org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

具体讲解可参照第三部分定义配置文件中的Layout。

5 log4j.appender.stdout.layout.ConversionPattern= [QC] %p [%t] %C.%M(%L) | %m%n

如果使用pattern布局就要指定的打印信息的具体格式ConversionPattern,打印参数如下:

%m 输出代码中指定的消息

%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL

%r 输出自应用启动到输出该log信息耗费的毫秒数

%c 输出所属的类目,通常就是所在类的全名

%t 输出产生该日志事件的线程名

%n 输出一个回车换行符,Windows平台为“rn”,Unix平台为“n”

%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921

%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。

[QC]是log信息的开头,可以为任意字符,一般为项目简称。

输出的信息 [TS] DEBUG [main] AbstractBeanFactory.getBean(189) | Returning cached instance of singleton bean 'MyAutoProxy'

具体讲解可参照第三部分定义配置文件中的格式化日志信息。

7 log4j.appender.R=org.apache.log4j.DailyRollingFileAppender

此句与第3行一样。定义名为R的输出端的类型为每天产生一个日志文件。

8 log4j.appender.R.File=D:\\Tomcat 5.5\\logs\\qc.log

此句为定义名为R的输出端的文件名为D:\\Tomcat 5.5\\logs\\qc.log

可以自行修改。

9 log4j.appender.R.layout=org.apache.log4j.PatternLayout

与第4行相同。

10 log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n

与第5行相同。

12 log4j.logger.com. neusoft =DEBUG

指定com.neusoft包下的所有类的等级为DEBUG。

可以把com.neusoft改为自己项目所用的包名。

13 log4j.logger.com.opensymphony.oscache=ERROR

14 log4j.logger.net.sf.navigator=ERROR

这两句是把这两个包下出现的错误的等级设为ERROR,如果项目中没有配置EHCache,则不需要这两

句。

15 log4j.logger.org.apache.commons=ERROR

16 log4j.logger.org.apache.struts=WARN

这两句是struts的包。

17 log4j.logger.org.displaytag=ERROR

这句是displaytag的包。(QC问题列表页面所用)

18 log4j.logger.org.springframework=DEBUG

此句为Spring的包。

24 log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN

25 log4j.logger.org.hibernate=DEBUG

此两句是hibernate的包。

以上这些包的设置可根据项目的实际情况而自行定制。

三、log4j详解

1、定义配置文件

Log4j支持两种配置文件格式,一种是XML格式的文件,一种是Java特性文件log4j.properties(键=值)。下面将介绍使用log4j.properties文件作为配置文件的方法:

①、配置根Logger

Logger 负责处理日志记录的大部分操作。

其语法为:

log4j.rootLogger = [ level ] , appenderName, appenderName, ?

其中,level 是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定义的级别。Log4j建议只使用四个级别,优 先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定 义了INFO级别,只有等于及高于这个级别的才进行处理,则应用程序中所有DEBUG级别的日志信息将不被打印出来。ALL:打印所有的日志,OFF:关 闭所有的日志输出。 appenderName就是指定日志信息输出到哪个地方。可同时指定多个输出目的地。

②、配置日志信息输出目的地 Appender

Appender 负责控制日志记录操作的输出。

其语法为:

log4j.appender.appenderName = fully.qualified.name.of.appender.class

log4j.appender.appenderName.option1 = value1 ?

log4j.appender.appenderName.optionN = valueN

这里的appenderName为在①里定义的,可任意起名。

其中,Log4j提供的appender有以下几种:

org.apache.log4j.ConsoleAppender(控制台),

org.apache.log4j.FileAppender(文件),

org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),

org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),可通过 log4j.appender.R.MaxFileSize=100KB设置文件大小,还可通过 log4j.appender.R.MaxBackupIndex=1设置为保存一个备份文件。

org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

例如:log4j.appender.stdout=org.apache.log4j.ConsoleAppender

定义一个名为stdout的输出目的地,ConsoleAppender为控制台。

③、配置日志信息的格式(布局)Layout

Layout 负责格式化Appender的输出。

其语法为:

log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class

log4j.appender.appenderName.layout.option1 = value1 ?

log4j.appender.appenderName.layout.optionN = valueN

其中,Log4j提供的layout有以下几种:

org.apache.log4j.HTMLLayout(以HTML表格形式布局),

org.apache.log4j.PatternLayout(可以灵活地指定布局模式),

org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),

org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

2、格式化日志信息

Log4J采用类似C语言中的printf函数的打印格式格式化日志信息,打印参数如下:

%m 输出代码中指定的消息

%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL

%r 输出自应用启动到输出该log信息耗费的毫秒数

%c 输出所属的类目,通常就是所在类的全名

%t 输出产生该日志事件的线程名

%n 输出一个回车换行符,Windows平台为“rn”,Unix平台为“n”

%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921

%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。

3、在代码中使用Log4j

我们在需要输出日志信息的类中做如下的三个工作:

1、导入所有需的commongs-logging类:

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

2、在自己的类中定义一个org.apache.commons.logging.Log类的私有静态类成员:

private final Log log = LogFactory.getLog(getClass());

LogFactory.getLog()方法的参数使用的是当前类的class。

3、使用org.apache.commons.logging.Log类的成员方法输出日志信息:

if (log.isDebugEnabled()) {

log.debug(\ }

if (log.isInfoEnabled()) {

log.info(\ }

if (log.isWarnEnabled()) {

log.warn(\ }

if (log.isErrorEnabled()) {

log.error(\ }

if (log.isFatalEnabled()) {

log.fatal(\ }

LOG4J 使用总结

本文来源:https://www.bwwdw.com/article/v1fp.html

Top