Java程序最常用的日志系统大概就是apache的log4j了,它的功能简单说就是“记录日志”。 它主要由logger、appender和layout这3个对象构成,logger是一个具体的“记录器”,appender是记录器的“输出对象”,它可以是屏幕输出、文件、界面组件、socket等。layout是appender的属性,决定appender所代表的输出中,一条具体的记录由哪些信息组成,排列顺序等。
每一个logger都有一个名字,名字是logger初始化时由getLogger的参数决定的,例如下面的logger的名字是com.foo:
Logger logger = Logger.getLogger("com.foo");
名字是logger的唯一标识符,例如下面的x和y两个logger实际上是同一个对象:
Logger x = Logger.getLogger("wombat");
Logger y = Logger.getLogger("wombat");
名字还具有继承性,例如名为com.foo.bar的logger是com.foo这个logger的子logger,com.foo又是com的子logger,子logger会继承所有上级logger的appender。这种继承类似于java包的父目录和子目录的关系,详见[1]的"Named Hierarchy"部分。
类似于根目录的概念,rootLogger是logger hierarchy的顶端,简单的log4j应用中,只定义rootLogger的appender,所有类中的logger就继承了rootLogger的特性。
为一个logger指定appender是在log4j配置文件中定义的,格式是:
log4j.rootLogger=level_name, appender_name1, appender_name2, ...
或: log4j.logger.logger_name=level_name, appender_name1, appender_name2, ...
前者为rootLogger指定appender,后者为某一个具体的logger指定appender。定义appender属性的方法是:
log4j.appender.appender_name=...
log4j.appender.appender_name.layout=...
例如下面的代码为rootLogger指定了appender A1,并设置A1为界面输出,然后指定了输出的格式,最后一行指定了com.foo的输出级别为WARN,com.foo及其子logger低于WARN的日志将不记录,由于com.foo没有指定appender,所以继承rootLogger的A1作为其输出:
log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
log4j.logger.com.foo=WARN
logger的级别常用的有debug, info, warn, error四种,详见“ log4j日志的输出级别设置 ”;appender常用的有 ConsoleAppender(控制台输出)、 DailyRollingFileAppender(按照一定的频率滚动输出日志,例如每月、每周、每天、每小时等)和 RollingFileAppender(到一定文件大小时滚动输出) 三种;layout常用的有SimpleLayout, PatternLayout, HTMLLayout, XMLLayout四种,后两种用来输出html和xml文本。不论哪种layout,都输出的是纯文本,因此各种appender与各种layout可以随意组合。
如果对项目中一些类的日志进行特殊处理(例如更改输出级别、指定新的输出文件等),见笔记“ 在包一级定制log4j日志输出 ”。
下面是一个完整的日志演示,首先是测试用例,只打一条日志:
package com.boco.godu.gapi.logger;
import org.apache.log4j.Logger;
import org.junit.Test;
public class Log4jDemo {
private final Logger logger = Logger.getLogger(this.getClass());
@Test
public void testGapiLogger() {
logger.info(" Apache Logger ");
}
}
log4j.properties文件:
log4j.rootLogger=debug, console, ft, fh, fx
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.SimpleLayout
log4j.appender.ft=org.apache.log4j.RollingFileAppender
log4j.appender.ft.File=./log/debug.log
log4j.appender.ft.Append=false
log4j.appender.ft.MaxFileSize=2MB
log4j.appender.ft.MaxBackupIndex=10
log4j.appender.ft.layout=org.apache.log4j.PatternLayout
log4j.appender.ft.layout.ConversionPattern=%d{MM-dd HH:mm:ss,SSS} %t %c,%L %p - %m%n
log4j.appender.fh=org.apache.log4j.RollingFileAppender
log4j.appender.fh.File=./log/debug.html
log4j.appender.fh.Append=false
log4j.appender.fh.MaxFileSize=2MB
log4j.appender.fh.MaxBackupIndex=10
log4j.appender.fh.layout=org.apache.log4j.HTMLLayout
log4j.appender.fh.layout.LocationInfo=true
log4j.appender.fh.layout.Title=Test Log4j Layout
log4j.appender.fx=org.apache.log4j.RollingFileAppender
log4j.appender.fx.File=./log/debug.xml
log4j.appender.fx.Append=false
log4j.appender.fx.MaxFileSize=2MB
log4j.appender.fx.MaxBackupIndex=10
log4j.appender.fx.layout=org.apache.log4j.xml.XMLLayout
log4j.appender.fx.layout.LocationInfo=true
rootLogger一共挂了4个appender,分别是一个控制台输出,一个纯文本格式日志,一个html格式日志,一个xml格式日志。
运行测试用例后的效果如下(黑体字和红圈是源代码打出的日志):
控制台输出:
INFO - Apache Logger
纯文本文件:
08-11 16:04:03,343 main com.boco.godu.gapi.logger.Log4jDemo,11 INFO - Apache Logger
html文件:
xml文件:
<log4j:event logger="com.boco.godu.gapi.logger.Log4jDemo" timestamp="1313049843343" level="INFO" thread="main">
<log4j:message><![CDATA[ Apache Logger ]]></log4j:message>
<log4j:locationInfo class="com.boco.godu.gapi.logger.Log4jDemo" method="testGapiLogger" file="Log4jDemo.java" line="11"/>
</log4j:event>