浏览 449 次
|
该帖已经被评为新手帖
|
|
|---|---|
| 作者 | 正文 |
|
最后更新时间:2008-02-28 关键字: 工作心得
Log4j的简介:
Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。 log4j的好处在于: 1) 通过修改配置文件,就可以决定log信息的目的地——控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等 2) 通过修改配置文件,可以定义每一条日志信息的级别,从而控制是否输出。在系统开发阶段可以打印详细的log信息以跟踪系统运行情况,而在系统稳定后可以关闭log输出,从而在能跟踪系统运行情况的同时,又减少了垃圾代码(System.out.println(......)等)。 1、关于Log的根: root类别位于logger继承结构的最上层,特性: 1)它一直存在. (2)它不能根据名称而获得,调用类的静态方法Logger.getRootLogger获得. 所有的Logger可以通过静态方法Logger.getRootLogger获得而得到它们自己的实例. Logger类的方法: 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); // generic printing method: public void log(Level l, Object message); } 2、log4j中的优先级别: Loggers可以被分配级别,org.apache.Log4j.Level 类中定义了DEBUG,INFO,WARN,ERROR,FATAL级别的集合. 如果一个Logger没有被分配一个级别,那么它将从离它最近一个被分配了级别的ancestor那里继承。 Logger的输出的实例方法之一实现日志的请求.输出的方法有:debug,info,warn,error,fatal和log。 通过定义输出方法区分日志的请求的级别.如果C是一个Logger的实例,那么声明C.info("....")就是一个INFO级别的日志请求.如果一个日志的请求的级别高于或等于日志的级别那么它就能被启用,反之将被禁用. 对于标准级别的大小关系:DEBUG<INFO<WARN<ERROR<FATAL //取得名为com.foo的实例: Logger logger = Logger.getLogger("com.foo"); //设置它的级别: cat.setLevel(Level.INFO); //一般都是通过配置文件来设置的. //barlogger继承了logger Logger barlogger = Logger.getLogger("com.foo.Bar"); //这个请求可用,因为WARN >= INFO logger.warn("Low fuel level."); //这个请求不可用,因为: DEBUG < INFO. logger.debug("Starting search for nearest gas station."); //下面请求也为可用 barlogger.info("Located nearest gas station."); //可以调用getLogger方法将返回一个同名的Logger对象的实例. Categoty x = Logger.getLogger("wombat") Categoty y = Logger.getLogger("wombat") //x和y参照的是同一个Logger对象. 这样我们就可以先定义一个Logger.然后在代码的其它地方不需要传参就可以重新得到我们已经定义的Logger的实例. Log4j的loggers可以在任何顺序创造和配置,特别是,一个后实例化的"parent"logger能够找到并且连接它的子logger. 3、log4j通过软件组件命名logger: 使用Log4j,首先就是获取日志记录器,这个记录器将负责控制日志信息。其语法为: public static Logger getLogger( String name), 通过指定的名字获得记录器,如果必要的话,则为这个名字创建一个新的记录器。Name一般取本类的名字,比如: static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () ) ; Log4j使得通过软件组件命名logger很容易。我们可以通过Logger的静态的初始化方法在每一个类里定义一个logger,令logger的名字等于类名的全局名,而实现logger的命名。这是一个实效的简单的定义一个logger的方法。因为日志输出带有产生日志的类的名字,这个命名策略使得我们更容易定位到一个日志信息的来源。虽然普通,但却是命名logger的常用策略之一。 Log4j没有限制定义logger的可能。开发员可以自由的按照它们的意愿定义logger的名称。 然而,以类的所在位置来命名Logger好象是目前已知的最好方法。 可以通过logger的静态的初始化方法在每一个类里定义一个logger,令logger的名字等于类名的全局名,而实现logger的命名,Log4j命名没有限制.这样做能对日志中的信息精确的定位. 一个logger可以设置超过一个的appender这样可以允许日志请求被输出到输出源。 可以用addAppender方法添加一个appender到一个给定的logger。 一个logger继承另一个logger时也将父辈的appender继承过来了。 我们也可以通过设置appender的additivity flag 为false,来重载appender的默认行为,以便继承的属性不在生效,但它的子类仍会继承它的属性。 配置日志信息输出目的地Appender,其语法为: log4j.appender.appenderName=fully.qualified.name.of.appender.class log4j.appender.appenderName.option1 = value1 … … log4j.appender.appenderName.option = valueN 其中,Log4j提供的appender有以下几种的输出目的地: a. org.apache.log4j.ConsoleAppender,将日志信息输出到控制台 b.org.apache.log4j.FileAppender,将日志信息输出到一个文件 c.org.apache.log4j.DailyRollingFileAppender,将日志信息输出到一个,并且每天输出到一个新的日志文件,按照不同的配置可以定义每月一个日志文件,或者每周,每天,每小时,每分钟等输出一个新的日志文件。 d. org.apache.log4j.RollingFileAppender,将日志信息输出到一个文件,通过指定文件的的尺寸,当文件大小到达指定尺寸的时候会自动把文件改名,如名为example.log的文件会改名为example.log.1,同时产生一个新的example.log文件。如果新的文件再次达到指定尺寸,又会自动把文件改名为example.log.2,同时产生一个example.log文件。依此类推,直到example.log. MaxBackupIndex,MaxBackupIndex的值可在配置文件中定义。 e. org.apache.log4j.WriterAppender,将日志信息以流格式发送到任意指定的地方。 f.org.apache.log4j.jdbc.JDBCAppender,通过JDBC把日志信息输出到数据库中。 g.org.apache.log4j.net.SMTPAppender,将日志信息以邮件的方式发送到指定的邮箱。 注意:logger C的一个祖先logger P,它的附加标志被设为false(默认为true),那么C的输出将被定位到所有C的appender,以及从开始上溯到P的所有ancestor logger的appender. P的appender仍会被定位. 4、layout用来定义appender的输出格式: PatternLayout,作为Log4j标准版中的一部分让用户类似C语言的printf方法的格式来输出. 转化模式为"%r [%t] %-5p %c - %m%n"的PatternLayout将输出类似如下的信息: 176 [main] INFO org.foo.Bar - Located nearest gas station. 第一个栏位是程序开始后消逝的毫秒数. 第二个栏位是做出日志的线程. 第三个栏位是log的级别. 第四个栏位是日志请求相关的logger的名字.-后是文字的信息的表述. Log4j将根据用户定义的公式来修饰日志信息的内容.例如你经常需要记录Oranges,一个在你当前的项目被用到的对象类型,那么你可以注册一个OrangeRenderer,它将在一个orange需要被记录时被调用. 对象渲染类似类的结构继承,例如oranges的一个实例fruits,如果你注册一个FruitReanderer,所有的水果包括oranger将被FruitReanderer所渲染.除非你注册了一个orange. 注意:对象渲染必须实现ObjectRenderer接口. 配置日志信息的格式(布局),其语法为: log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class log4j.appender.appenderName.layout.option1 = value1 ... log4j.appender.appenderName.layout.option = valueN 其中Log4j提供layout 有以下几种: a.org.apache.log4j.HTMLLayoutHTML (以HTML表格形式布局) b.org.apache.log4j.PatternLayout (可以灵活地指定布局模式) c.org.apache.log4j.SimpleLayout (包含日志信息的级别和信息字符串) d.org.apache.log4j.TTCCLayout (包含日志产生的时间,线程,类别等等信息) e.Log4J 采用C语言中的 printf 函数的打印格式化日志信息 %m 输出代码中指定的消息 %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL %r 输出自应用启动到输出该log信息耗费的毫秒数 %c 输出所属的类目,通常就是所在的类的全名 %t 输出产生该日志事件的线程名 %n 输出一个回车换行符,Windows平台为"\r\n",Unix平台为"\n" %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS}输出类似2002 年10月 18日 22:10:28,921 %l 输出日志事件的发生位置,包括类目名,发生的线程,以用在代码中的行数.举例:Testlog4.main(TestLog4.java:10) %F输出日志事件的发生文件名. %L输出日志事件的发生行数. 这里是一个非常简单的例子,程序实现了 HTMLLayout和WriterAppender: import java.io.*; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.HTMLLayout; import org.apache.log4j.WriterAppender; public class HtmlandWrite { static Logger logger = Logger.getLogger(HtmlandWrite.class); public static void main(String args[]) { HTMLLayout layout = new HTMLLayout(); WriterAppender appender = null; try { FileOutputStream output = new FileOutputStream("output2.html"); appender = new WriterAppender(layout,output); } catch(Exception e) {} logger.addAppender(appender); logger.setLevel((Level) Level.DEBUG); logger.debug("Here is some DEBUG"); logger.info("Here is some INFO"); logger.warn("Here is some WARN"); logger.error("Here is some ERROR"); logger.fatal("Here is some FATAL"); } } 输出结果: package cn.Log4j; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.apache.log4j.ConsoleAppender; public class ConsandPatt { static Logger logger = Logger.getLogger(ConsandPatt.class); public static void main(String args[]) { // Note, %n is newline String pattern = "Milliseconds since program start: %r %n"; pattern += "Classname of caller: %C %n"; pattern += "Date in ISO8601 format: %d{ISO8601} %n"; pattern += "Location of log event: %l %n"; pattern += "Message: %m %n %n"; PatternLayout layout = new PatternLayout(pattern); ConsoleAppender appender = new ConsoleAppender(layout); logger.addAppender(appender); logger.setLevel((Level) Level.DEBUG); logger.debug("Here is some DEBUG"); logger.info("Here is some INFO"); logger.warn("Here is some WARN"); logger.error("Here is some ERROR"); logger.fatal("Here is some FATAL"); } } 执行结果: Milliseconds since program start: 0 Classname of caller: cn.Log4j.ConsandPatt Date in ISO8601 format: 2008-01-12 06:00:46,765 Location of log event: cn.Log4j.ConsandPatt.main(ConsandPatt.java:38) Message: Here is some DEBUG Milliseconds since program start: 0 Classname of caller: cn.Log4j.ConsandPatt Date in ISO8601 format: 2008-01-12 06:00:46,765 Location of log event: cn.Log4j.ConsandPatt.main(ConsandPatt.java:40) Message: Here is some INFO Milliseconds since program start: 0 Classname of caller: cn.Log4j.ConsandPatt Date in ISO8601 format: 2008-01-12 06:00:46,765 Location of log event: cn.Log4j.ConsandPatt.main(ConsandPatt.java:42) Message: Here is some WARN Milliseconds since program start: 0 Classname of caller: cn.Log4j.ConsandPatt Date in ISO8601 format: 2008-01-12 06:00:46,765 Location of log event: cn.Log4j.ConsandPatt.main(ConsandPatt.java:44) Message: Here is some ERROR Milliseconds since program start: 16 Classname of caller: cn.Log4j.ConsandPatt Date in ISO8601 format: 2008-01-12 06:00:46,781 Location of log event: cn.Log4j.ConsandPatt.main(ConsandPatt.java:46) Message: Here is some FATAL java properties(key=value)文件: 假定有一个用了Log4j和程序MyApp. import com.foo.Bar; //Import Log4j 相关类. 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 "MyApp". static Logger logger = Logger.getLogger(MyApp.class); public static void main(String[] args) { //创建了一个相当简单的Log4j设置,加入一个ConsoleAppender 到根logger,默认采用输出格式:"%-4r [%t] %-5p %c %x - %m%n". BasicConfigurator.configure(); logger.info("Entering application."); Bar bar = new Bar(); bar.doIt(); logger.info("Exiting application."); } 调用的类: package com.foo; import org.apache.Log4j.Logger; public class Bar { static Logger logger = Logger.getLogger(Bar.class); //继承自根的logger默认被分配了Level.DEBUG的级别. public void doIt() { logger.debug("Did it again!"); } } 输出为: 0 [main] INFO Log4jTest - Entering application. 0 [main] DEBUG Bar - Did it again! 0 [main] INFO Log4jTest - Exiting application. MyApp类配置Log4j是通过调用BasicConfigurator.configure方法.其它的类仅仅需要引入org.apache.Log4j.Logger 类找到它们希望用的 logger 并用它就行了. 5、用配置文件来配置Log4j: 现在Log4j支持XML和java properties(key=value)文件下几种格式. XML: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.SimpleLayout"/> </appender> <root> <priority value ="debug" /> <appender-ref ref="ConsoleAppender"/> </root> </log4j:configuration> 文件以标准的XML声明作为开始,后面跟着指出DTD(文档类型定义)的DOCTYPE声明,它定义了XML文件的结构,例如,什么元素可以嵌入在其他元 素中等等。上面文件在log4j发行版的src/java/org/apache/log4j/xml目录中。 接着看看封装所有元素的 log4j:configuration 元素,它在DOCTYPE声明中被指定为根元素。 这里创建一个名叫"ConsoleAppender"的 Appender,注意,你可以选择任何名字,该示例之所以选择"ConsoleAppender",完全是为了示例的设计。接着这个appender类 以全名形式给出,经常用规范(fully qualified)类名。 Appender必须具有一个指定的 name和class。嵌入在 Appender之内的是 layout元素,这里它被指定为SimpleLayout。 Layout 必须具有一个 class属性。 root元素必须存在且不能被子类化。示例中的优先级被设置为"debug",设置appender饱含一个appender-ref元素。还有更多的属 性或元素可以指定。查看log4j发行版中的src/java/org/apache/log4j/xml/log4j.dtd以了解关于XML配置文件 结构的更多信息。可以用下面这种方法把配置信息文件读入到Java程序中: DOMConfigurator.configure("configurationfile.xml"); DOMConfigurator 用一棵DOM树来初始化log4j环境。这里是示例中的XML配置文件:plainlog4jconfig.xml。这里是执行该配置文件的程序: files/externalxmltest.java: 为了方便日志输出可以在运行时刻被控制.这里提供一个小小修改的版本: 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("Entering application."); Bar bar = new Bar(); bar.doIt(); logger.info("Exiting application."); } } 修改后的MyApp通知程序调用PropertyConfigurator()方法解析一个配置文件,并用根据这个配置文件来设置日志. 配置文件内容: 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 打印结果: 2008-01-11 14:01:07,500 [main] INFO cn.Log4j.Log4jTest - Entering application. 2008-01-11 14:01:07,515 [main] DEBUG cn.Log4j.Bar - Did it again! 2008-01-11 14:01:07,515 [main] INFO cn.Log4j.Log4jTest - Exiting application. 另一个配置文件,它使用了多个appenders. 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.FILE.Encoding=GBK 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=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n 注意:我们不需要重新编译代码就可以获得这些不同的日志行为.它可以适应输出到不同的系统,或者转发日志到一个远程的log4j服务器.它根据本地server的策略来进程日志输出. 在避免日志被禁用时产生不必要的花费,输出日志时要可以这样写: if(logger.isDebugEnabled() { //判断Debut是否可用 logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i])); } 给出日志的邮件通知: log4j.rootLogger=INFO,MAIL log4j.addivity.org.apache=true log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender log4j.appender.MAIL.cn.Log4j=FATAL log4j.appender.MAIL.BufferSize=10 log4j.appender.MAIL.From=zhangsaim@sina.com log4j.appender.MAIL.SMTPHost=smtp.sina.com log4j.appender.MAIL.SMTPUsername=zhangsaim log4j.appender.MAIL.SMTPPassword=11234567 log4j.appender.MAIL.Subject=Log4J Message log4j.appender.MAIL.To=zhangsai2@yahoo.com.cn log4j.appender.MAIL.layout=com.sun.DefineLayOut log4j.appender.MAIL.layout.ConversionPattern=[framework]%d-%c-%-4r[%t] %-5p%c %x Message:%m%n 6、处理中文乱码: 我们可以写一个布局模式。如果你要使用PatternLayout,我们就写一个PatternLayout的子类,覆盖HTMLLayout的getContentType方法即可。假如我要用org.apache.log4jPatternLayout。我们就可以写一个DefineLayOut类,代码如下: package com.sun; import org.apache.log4j. PatternLayout; public class DefineLayOut extends PatternLayout{ public String getContentType() { return "text/html;charset=GBK"; } } 遇到中文会出现乱码,我们可以把这个配置文件log4j.properties用jdk的工具native2asii转换一下编码方式。 命令:native2ascii 源文件名 目标文件名 把这个log4jxx.properties改名为log4j.properties取代原来的log4j.properties就ok了。 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
最后更新时间:2008-02-28
大家一起交流哈 |
|
| 返回顶楼 | |
|
最后更新时间:2008-03-06
|
|
| 返回顶楼 | |



