使用log4j为Tomcat输出日志
http://tomcat.apache.org/tomcat-6.0-doc/logging.html#Using_Log4j
原出处:
Geoff Mottram (geoff at minaret dot biz).
Placed in the public domain on August 28, 2004 by the author.
Last updated: January 27, 2005.
This document is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the author be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with this document or the use or other dealings in this document.
简介
为了能够满足我的一个项目中日志输出的特殊要求,我花了好几个小时配置log4j为Tomcat5.0.28输出日志。本文说明了一些机制,并且描述了配置Tomcat每日生成一个日志文件的步骤,涵盖Tomcat5.0.x和5.5.x版本。
注: 最新的log4j 1.3 alpha测试版已经支持每日生成一个日志文件。参考本文相关链接了解如何进行安装和配置。
Tomcat 5.0.x的日志
Tomcat 5.0.x主要由两个途径记录日志信息。分别为标准日志输出文件catalina.out和一般情况下在文件名中包含有日期的
Servlet日志文件(如:catalina.2004-08-27.log
)。
catalina.out中的数据主要有三个来源:输出至标准输入和标准错误输出的数据,
通过Commons Logging接口输出的日志信息,还有一种是包括了Tomcat各种事件状态和其它系统(如Jakarta Struts)的输出。使用Commons Logging接口可以根据配置输出多种多样的日志数据形式。
The data in the Servlet的日志数据是调用ServletContext 类的log()方法产生的,例如:
httpServletRequest.getSession().getServletContext().log("Some message");
要保存输出信息到日志文件,你需要在Tomcat的配置文件(Tomcat的conf目录下)server.xml
中对FileLogger配置,一般如下:
<!-- Global logger unless overridden at lower levels -->
<Logger className="org.apache.catalina.logger.FileLogger"
prefix="servlet." suffix=".log" timestamp="true" />
Servlet日志可以打开(配置了FileLogger)和关闭(没有配置FileLogger),但是没有办法指定日志输出级别(只能输出INFO以及更高级别的日志信息)。尽管Tomcat的文档中提到它所有的Logger都支持verbosity
配置项,但是好像没有什么效果。
如果希望配置Tomcat捕获所有的日志数据,输出到每日生成一个的日志文件(如:在文件名中表明产生日期)。Tomcat中FileLogger提供一种标准方法用于捕获Servlet日志流并每天生成一个新的文件。你可以对日志文件进行备份、删除、分析或者你希望的其它操作。
如果Tomcat再有一个使用Commons Logging接口的Catalina Logger就好了,可以让你更好的控制输出的格式,虽然这个模块很相当容易实现的,但是谁有时间来做啊。后面会告诉大家如何控制catalina.out。
Tomcat 5.5.x的日志
Tomcat 5.5.x有两条途径记录日志数据,写入标准输出和标准错误输出的所有内容还是记录在文件catalina.out,其余的所有日志都通过
Commons Logging 接口输出。如果你没有配置用来其它的Logger(如log4j),所有的日志信息(包括通过commons-logging输出的所有内容)都会输出到catalina.out,致使其不断增长。
Tomcat 5.5.x比Tomcat 5.0.x的一项改进是Servlet日志不在存在了,Servlet日志是用来接收任何传递给ServletContext 类的log()方法的内容,例如:
httpServletRequest.getSession().getServletContext().log("Some message");
Tomcat 5.5.x现在将这些信息通过commons-logging接口输出为INFO级别的日志。如果配置了像log4j这样的logger,你可以把所有的日志信息输入到每日生成的日志文件(如:在文件名中表明产生日期)中,你可以对日志文件进行备份、删除、分析或者你希望的其它操作。
Tomcat通用日志
如上所述,在catalina.out文件中的大部分数据都是通过调用Commons Logging接口产生的,Commons Logging可以让你在运行期对日志输出细节进行控制,并允许使用多种后台日志系统,Tomcat标准发行版使用SimpleLog作为日志系统,SimpleLog将所有的内容都输出到标准错误输出,对于Tomcat来说,默认被重定向到catalina.out文件,这样就造成catalina.out文件不停的增长,不生成循环的日志文件。
Log4j
Log4j是支持Commons Logging的强大日志系统,可以添加到你的Tomcat中替换SimpleLog以支持循环的日志文件和多样化的配置。事实上,你不但可以将日志输出到文件,也可以输出到操作系统日志,或者远程机器等其它的目标,你还可以输出至不止一个地方。要在你的Tomcat中使用log4j系统可以按照如下步骤进行安装配置(注:这是针对log4j 1.2.x版本,1.3.x alpha测试版本的安装和配置可以参考附录中的相关链接):
commons-logging.jar
解压缩到你Tomcat安装路径的common/lib目录中。
log4j-1.2.12.jar
解压缩到你Tomcat安装路径的common/lib目录中。
common/classes
创建log4j的配置文件log4j.properties
(配置文件在随后一节)。 这里描述的配置会导致在Tomcat 5.5.x中创建两个日志文件,在Tomat 5.0.x中创建三个文件:一个是Servlet日志文件(仅对Tomcat 5.0.x),在每天晚上循环产生新的日志文件;第二个是通过log4j输出的Commons Logging 日志文件(也会在每天晚上循环产生新的日志文件),还有一个是仅仅包含了打印到标准输出和标准错误输出的catalina.out
文件,这个文件仍然会不断的增长,但是如果你的Tomcat应用程序设计的比较好,不是使用标准输出和标准错误输出,这就不成问题了(其实,这个文件应该大小为0)。
注意,commons-logging.jar
和log4j.jar
files是安装在Tomcat的common/lib
目录中,而log4j.properties文件是安装在common/classes
目录中。这样的配置可以让Tomcat和你的Web应用程序都能够使用log4j。如果你的Web应用程序使用Commons Logging接口,那么其日志数据将会输出到Tomcat服务的日志中。你也可以修改log4j的配置文件log4j.properties,将你的应用程序日志输出到其它文件中(配置方法请参考log4j的其它文档)。
Log4j配置文件
log4j.properties
文件可以如下配置:
# # Configures Log4j as the Tomcat system logger # to output info level messages into a rolling log file.
# log4j.rootLogger=INFO, R
# # To continue using the "catalina.out" file (which grows forever), # comment out the above line and uncomment the next.
# #log4j.rootLogger=ERROR, A1
# # Configuration for standard output ("catalina.out"). #
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
# # Configuration for a rolling log file ("tomcat.log"). # log4j.appender.R=org.apache.log4j.DailyRollingFileAppender log4j.appender.R.DatePattern='.'yyyy-MM-dd
# # Edit the next line to point to your logs directory. # The last part of the name is the log file name. # log4j.appender.R.File=/usr/local/tomcat/logs/tomcat.log log4j.appender.R.layout=org.apache.log4j.PatternLayout
# # Print the date in ISO 8601 format # log4j.appender.R.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
# # Application logging options #
#log4j.logger.org.apache=DEBUG #log4j.logger.org.apache=INFO #log4j.logger.org.apache.struts=DEBUG #log4j.logger.org.apache.struts=INFO
你只需要修改这一行:
log4j.appender.R.File=/usr/local/tomcat/logs/tomcat.log
将路径修改为你的Tomcat的logs目录,如果你的系统环境配置了CATALINA_HOME环境变量,那么可以使用${catalina.home}/logs/tomcat.log进行配置即可。
上面的log4j配置仅记录比较重要的日志(警告warning、错误error、致命错误fatal)到Tomcat的logs目录下的tomcat.log文件中,每天晚上过0点的第一条信息会触发重命名tomcat.log,将当前日期附加在tomcat.log文件名中,并产生新的tomcat.log文件。
使用log4j DailyRollingFileAppender
不爽的一点是为了产生循环的日志文件,必须输出一条日志信息来触发,如果你每天晚上使用cron来处理你的日志文件就会存在问题。Tomcat自带的FileLogger总是在当天的日志文件名中加上日期来解决这个问题。我(Geoff)已经写了一个自定义的Log4j appender 来模仿Tomcat的FileLogger,大家可以免费使用(包括源代码)。在separate technical tip有DatedFileAppender的安装和配置信息。
注意:新的log4j 1.3.x alpha测试版已经支持按日滚动的日志文件。参考Log4j Version 1.3 and Apache Tomcat了解如何进行安装和配置。
你可以仿照配置文件最后几行的做法来覆盖默认的日志级别,来为你的应用程序做特殊配置。在正式运行环境中,你可能希望尽量减少日志输出,你可以修改这一行:
log4j.rootLogger=INFO, R
为:
log4j.rootLogger=ERROR, R
警告
在将日志输出级别修改为DEBUG时一定要小心(特别像log4j.logger.org.apache
),会造成大量的日志,相当大程度上拖慢你的系统速度。
Tomcat 启动
请注意,你必须安装commons-logging.jar到Tomcat的common/lib
目录中,你可能已经注意到,在Tomcat的已经有一个commons-logging-api.jar文件了
。这个jar文件是commons-logging.jar的简版,只实现了SimpleLog及类似的其它部分,只能基本满足
系统启动时的日志输出,因为没有日志系统的API,Tomcat是不能启动的。如果在启动classpath中没有加入日志系统(如log4j),是不可以用commons-loging.jar来进行
替换这个文件的。
在启动过程中的一些类载入时,如果你在common/lib目录中加入了完整版的commons-logging.jar
,它会替换commons-logging-api.jar的类,会重新初始化日志系统,并尝试定位log4j或其它你使用的日志系统
。
应用程序日志
你可以在你的Servlet程序中使用Servlet日志(如servletContext.log("Some message")
)来记录消息,或者利用Commons Logging接口。本节介绍在上述集成后,使用更好的日志方法来演示日志的加强。
例程:
package com.acme.webapp;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
public class MyApplication {
private Log myLog;
public MyApplication() { myLog = LogFactory.getLog(MyApplication.class); }
public void process() { // Do some processing
myLog.debug("A debug message");
// Do something else
myLog.info("An information message");
// etc. } }
Log对象可以声明为静态的类成员变量,在多个类对象间共享,换句话说,你的整个程序可以共享唯一的一个Log对象,或者多个Log对象,在运行期控制多种日志生成方法。你将类的全限定名称传递给LogFactory.getLog()方法,来唯一标识log对象,在上面的例子中,Log的名字应该是com.acme.webapp.MyApplication。给每个Log对象一个名字,可以在log4.properties中用相同的表示控制日志输出。这样,你可以增加下面一行,为你的应用定义输出DEBUG信息:
log4j.logger.com.acme.webapp.MyApplication=DEBUG
可以使用任何字符串来命名Log对象,但是,按照惯例,是用类的class来命名Log对象,参考log4j的FAQ了解命名方法。
昨天同事那边出了点故障, 一台tomcat服务器访问出错,tomcat是6.0版本的, 然后想查看tomcat日志却怎么也找不到最近的日志,logs下面 只有08年的几个日志文件。同事感觉很晕, 我也觉着奇怪, 照理说, tomcat默认情况下也是会生成日志文件的, 这回怎么就平白无故的消失了呢?
到网上找了下相关的信息, 网上大部分都是说的如何让tomcat使用log4j。我想tomcat默认用的是jdklogger,如果能换用log4j也不错, 只要日志能生成出文件来。
于是在我的本机环境的tomcat5.5和tomcat6下分别作了实验。
结果,发现tomcat5.5和6在配置log4j的时候还存在差异。
1)tomcat5.5
把 commons-logging和log4j的jar包分别copy到common/lib下面, 再copy一份log4j.properties和commons-logging.properties到common/classes之下,
log4j.properties,配置可以如下:
写道
commons-logging.properties,配置可以如下:
重启tomcat之后,就能在logs/下面找到日志文件了。
2)tomcat6
同样的, 也要复制commons-logging和log4j的jar包到tomcat, 不过目标目录不同,位于:${tomcat_home}/lib/;
commons-logging.properties和log4j.properties需要复制到${tomcat_home}/lib/目录下;
额外的,还需要到http://www.apache.org/dist/tomcat/tomcat-6/v6.0.18/bin/extras/
下载两个包:tomcat-juli.jar,tomcat-juli-adapters.jar
tomcat-juli.jar复制到bin下面,替换原有的同名jar包;tomcat-juli-adapters.jar 放到${tomcat_home}/lib/
完成以上步骤之后, 重启tomcat,就能发现已经有了log4j的日志文件产生。
参考资料:
http://tomcat.apache.org/tomcat-5.5-doc/logging.html
http://tomcat.apache.org/tomcat-6.0-doc/logging.html
http://www.blogjava.net/Unmi/archive/2008/07/07/213001.html