Log4j 是 Apache 的一个开放源代码项目,通过使用 Log4j ,可以控制日志文件, 输出的目的地 ,日志的输出格式,定义每一条日志的级别 。
实例:
以log4j.properties文件配置为例。
1. 在WEB-INF/classes目录中创建log4j.properties文件,内容如下:
log4j.rootLogger=DEBUG,A1
log4j.logger.log4jTestLogger=WARN,A2
#A1
log4j.appender.A1=org.apache.log4j.RollingFileAppender
log4j.appender.A1.File=c:/log.html
log4j.appender.A1.layout=org.apache.log4j.HTMLLayout
log4j.appender.A1.MaxFileSize=500KB
log4j.appender.A1.MaxBackupIndex=1
log4j.appender.A1.layout.ConversionPattern=%r%d{yyyy-MM-ddHH:mm:ss,SSS}%c%p-%m%n
#A2
log4j.appender.A2=org.apache.log4j.ConsoleAppender
log4j.appender.A2.layout=org.apache.log4j.SimpleLayout
log4j.appender.A2.layout.ConversionPattern=%d{yyyy-MM-ddHH:mm:ss,SSS}[%c][%p]%m%n
在需要输出日志信息的文件中获取logger类的引用,调用logger类的方法输出日志信息:
Logger logger=Logger.getLogger("log4jTestLogger"); //获取配置好的logger类的引用
logger.debug("This is DEBUG info from "+logger.getName()); //输出debug级别的信息
logger.info("This is INFO info from "+logger.getName());
logger.warn("This is WARN info from "+logger.getName());
logger.fatal("This is FATAL info from "+logger.getName());
logger.error("This is ERROR info from "+logger.getName());
对于一个logger,它的每个生效的日志信息都被转发到该logger的所有appender和该logger的父logger的每个appender。所以此列中的日志信息会被转发到控制台和c:/log.html。
Log4j配置
对Log4j环境的配置就是对根Logger的配置,包括配置根Logger的级别、相关的Appender等,Log4j由3个重要的组件构成:日志信息优先级、日志信息输出目的地、日志信息输出格式。
配置的三种方法:
① 在程序中配置;
② 采用配置文件(使用配置文件更加灵活)
a. XML格式;
b.ava properties格式。
默认的Log4j配置文件典型的应用是在Web服务器环境下,这时应该将默认配置文件log4j.properties(或者log4j.xml)放在Web应用的WEB-INF/classes文件夹中。
log4j.properties语法
log4j.rootLogger=[level],appender1,appender2 //配置根Logger,定义根logger的级别和输出地
log4j.logger.log4jTestLogger=[level],appender1,appender2
log4j.appender.目的地名=Appender类名 // 配置日志信息输出目的地的Appender
log4j.appender.目的地名.属性=值
log4j.appender.目的地名.layout=Layout类名 //配置日志信息格式(布局)
log4j.appender.目的地名.layout.属性=值
在Web应用中使用Log4j
在Web应用中,可以将配置文件的加载工作放在一个单独的Servlet程序中,并在web.xml文件中配置该Servlet程序。在Servlet程序的初始化方法中读取Log4j配置文件中的配置信息,配置好Log4j环境,这样在其它的Web组件中就可以自由地使用Log4j的日志功能了。
servlet代码:
public class J2eeLog4jDemo extends HttpServlet{
public void destroy() { super.destroy();}
public void init() throws ServletException {
String prefix=getServletContext().getRealPath("/");
String file=getInitParameter("Log4j");
if (file!=null)
PropertyConfigurator.configure(prefix+file);
}
}
默认是调用BasicConfigurator.configure()来进行配置,这时配置文件是默认文件。
还可以采用动态配置,log4j提供了PropertyConfigurator.configure(参数)来动态配置,其中参数是一个文件名,这样就可以自己指定配置文件。
Ø Logger类
Logger由一个String类型的名字标识,大小写敏感。
根logger是所有logger的祖先,总是存在的,不可通过名字获取。通过调用 Logger.getRootLogger() 获得根logger。
a.Logger.getLogger(String name)
b. Logger.getLogger(Class clazz)
通过调用a或者b获得(或者创建)一个logger,后者相当于调logger.getLogger(clazz.getName())。
如:
Logger log = Logger.getLogger(TestLog4j.class)<=> Logger.getLogger("TestLog4j") 与Logger.getLogger(TestLog4j)区分开。
注意:用同名参数调用Logger.getLogger(String name)将返回同一个logger的引用,故可以在一个地方配置Logger,在另外一个地方获得配置好的Logge。Logger的创建可以按照任意的次序,即父Logger可以后于子Logger被创建,Log4j将自动维护Logger的继承树。
Logger的层次命名规则
如果一个子Logger没有定义日志级别,则它将继承父类的日志级别,否则不会继承。默认情况下,子Logger会继承父类的所有Appender,把它们加入到自己的Appender清单中,如果子Logger的additivity标志设置为false,那么它就不会继承父类的Appender。对于Appender的继承,是一种叠加性继承,而子记录器只继承父记录器的Appender,而不考虑更远的祖先情况,
如果对某个logger类进行了配置,子logger类就可以不配置,不配置时默认继承父logger类的配置,这样就可以减轻开发过程中配置logger的工作量。(Logger的层次命名规则:Log4j采用了一种树状的继承层次结构,Logger遵循类似于包的层次。)比如:
static Logger rootLog=Logger.getRootLogger();
static Logger log1=Logger.getLogger("test4j");
static Logger log2=Logger.getLogger("test4j.test4j2");
static Logger log3=Logger.getLogger("test4j.test4j2.test4j2");
static Logger log4=Logger.getLogger("test4j.test4j2.test4j3");
Ø Level类
每个Logger都分配了一个日志级别(Log level),用来控制日志信息的输出,未被分配Level的Logger 将继承它最近的父Logger的Log Level。
每条输出到Logger的日志请求(Logging Request)也都有一个Level,如果该日志请求的Level大于或等于该Logger的Log Level,则该日志被处理(称为Enabled);否则该日志请求被忽略,因此可以知道:
1.Logger的Log Level越低,表示该Logger越详细。
2.Logging request的Level越高,表示该日志信息越优先输出。
Level类预定义了一下几个级别:.ALL < DEBUG < INFO < WARN < ERROR < FATAL <OFF
常用的5个级别为: error >warn>info>debug>all
Log4j的核心原则:Logger只处理比自己优先级高的日志请求。
Ø Appender接口
Log4j的Appender接口决定了日志信息输出的位置,目前Log4j可以把日志信息输出到以下位置: 控制台,文件,GUI组件,NT事件记录器,套接口服务器,UNIX Syslog守护进程。
Logger与Appender 的对应关系以及Appender的输出位置是在配置文件中指定的。
Appender类名包括下面几种经常使用的类:
1.org.apache.log4j.ConsoleAppender
这种Appdner将日志信息送控制台显示。
2.org.apache.log4j.FileAppender
这种Appdner将日志信息送指定的文件保存。
log4j.appender.FA=org.apache.log4j.FileAppender
log4j.appender.FA.File=c:/test.log
3.org.apache.log4j.DailyRollingFileAppender
这种Appdner将日志信息按日期送不同的日志文件保存,每个日志文件保存一天的日志。
log4j.appender.DRA=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DRA.File=dglog
log4j.appender.DRA.DatePattern='.'yyyy-mm-dd
4.org.apache.log4j.RollingFileAppender
文件大小达到一定程度时产生一个新文件。
log4j.appender.RFA=org.apache.log4j.RollingFileAppender
log4j.appender.RFA.File=./dglog.log
log4j.appender.RFA.MaxFileSize=100KB
log4j.appender.RFA.MaxBackupIndex=1
当dglog.log满100KB时,自动转为dglog.log.1,然后再自动创建一个新的dglog.log文件,继续保存日志信息。
5.org.apache.log4j.WriterAppender
将日志信息以流的格式发送到任何地方。
Ø LayOut
Log4j的Layout类决定了日志信息输出的格式,现在Log4j可以按照以下几种格式输出日志信息。
Layout类名指定了日志信息的格式:
org.apache.log4j.HTMLLayout:以HTML表格式布局
org.apache.log4j.PatternLayout:可以灵活指定布局
org.apache.log4j.SimpleLayout:包含日志信息的级别和信息的布局
org.apache.log4j.TTCCLayout:包含日志产生时间、线程、类别的布局
格式符
当使用org.apache.log4j.PatternLayout格式时,需要使用下面的格式符来自己定义日志信息内容和格式:
%m:输出代码中指定的信息。
%p:输出优先级,例如:DEBUG、WARN、ERROR、FATAL。
%r:输出自应用启动到该日志信息输出所耗费的时间(毫秒)。
%c:输出所属的类目,通常是线程所在的类的全名。
%t:产生该日志信息的线程名。
%n:输出一个换行。
%d:输出日志时间点的日期或时间,格式默认为ISO-8859-1,可以在其后指定时间格式,比如:%d{yyyy年MM月dd日HH:mm:ss,SSS},这时输出为2010年08月19日 13:20:28,921。
%l:输出日志信息的发生位置,包括:类名,发生的线程以及在代码中的行数,比如:TestLog4.main (TestLog4.java:10)。
Ø 优化
一个中等规模的项目,每天可以产生成千上万个日志请求,处理每个日志请求的花费是可以计算的,这个花费要尽量的掉,这就是优化的基本原则,因此,开发人员竟许多努力用在测量和调试logging的优化上。Log4j要求快速和弹性,速度最重要,弹性其次。
① 日志为禁用时的的优化
日志禁用,日志被彻底关闭,一个日志请求的花费等于一个方法调用加上整数的比较时间,方法调用还包括参数构建的隐藏花费。
在Log4j中,Logger是类而不是接口,这也在很大程度上降低了动态化引起的花费(但也降低了动态化)。
② 日志状态为启用时的优化
当日志状态为enable时,Log4j仍然需要比较请求的级别与logger的级别,然而,logger可能没有被安排为同一级别,它们将从它们的父亲处继承,这样,在继承之前,logger可能要搜索它的父类。
典型的层次结构解析花费是logger彻底关闭的3倍,因此,日志状态为启用时,日志优化的目标是使层次的搜索尽可能快,例如:子logger紧连接到它的父logger上。
③ 日志输出时的优化
日志信息输出时的开销,主要花费在日志信息的格式化以及发送日志信息到输出源的开销,因此优化的目标是尽量使信息格式化完成的快,典型的开销是大约是100-300ms。