Tocat的日志系统
日志系统是一个记录信息的组件,在Catalina中,日志系统是一个简单的跟容器相关的组件。Tomcat在Catalina.logger包中提供了多个不同的日志系统。本章程序在ex07.pyrmont包中。SimpleContext和Bootstrap是从第六章中修改得到的。本章有三节组成,第一节介绍了Logger接口,该接口是所有的日志系统都要实现的。第二节介绍了Tomcat中的日志系统,第三节详细的介绍了本章的例子,该例子基于Tomcat的日志系统。
Logger接口我不想详述了,本来内容不多,书上讲的已经很详细了,它的两点:1、与容器相关联;2、设置信息的显示级别;此处略过,
我总结下Tomcat的日志系统,下面是Tomcat日志系统的类的UML图:
Tomcat的日志系统,在上面已经体现的很清楚了,在Catalina中有一个Logger接口,Tomcat中所有的日志系统都必须实现那个接口,在Catalina中的logger下,有一个LoggerBase类,这个类是个抽象类,它实现了Logger接口中除了log(String message)之外的所有的方法。
我来介绍下这个没有实现的方法:这个方法将传入的信息写入到一个servlet日志文件中,通常是一个事件的日志。servlet日志文件的名称和类型取决于servlet容器的。消息将被无条件的记录。我介绍下一个方法:log(String msg,Throwable throwable)
为传入的异常超类throwable在servlet日志中记录下它的解释信息和堆栈信息。这个servlet 日志的名称和类型取决于servlet容器。它通常 是一个事件日志。对于传入的信息,它将无条件的记录到日志文件上。
public void log(String msg, Throwable throwable) {
CharArrayWriter buf = new CharArrayWriter();
PrintWriter writer = new PrintWriter(buf);
writer.println(msg);
throwable.printStackTrace(writer);
Throwable rootCause = null;
if (throwable instanceof LifecycleException)
rootCause = ((LifecycleException) throwable).getThrowable();
else if (throwable instanceof ServletException)
rootCause = ((ServletException) throwable).getRootCause();
if (rootCause != null) {
writer.println("----- Root Cause -----");
rootCause.printStackTrace(writer);
}
log(buf.toString());
}
按照上面方法的思路,顺带着介绍下public void log(String msg,Throwable throwable,int verbosity),将传入的信息和异常写入到日志文件中,通常是一个事件日志。如果传入的日志级别大于等于默认的级别之后,记录下上面两个信息。
按照上面给出的UML类图的类文件的结构,介绍Tomcat日志系统中的三个类。
logger.SystermOutLogger and logger.SystermErrLogger比较相似。他们都只是实现上面的基类之后,实现log(String message),方法。实现的方法也比较简单
public void log(String msg) {
System.err.println(msg);
}
前者与它的不同在于它打印日志的时候使用的 System.out.println(msg);
tomcat日志系统最复杂的日志系统就是FileLogger,文件日志系统。它将从关联容器收到的信息写入到文件中,每个信息可以选择性的加上时间戳。
public void log(String msg) {
// Construct the timestamp we will use, if requested
Timestamp ts = new Timestamp(System.currentTimeMillis());
String tsString = ts.toString().substring(0, 19);
String tsDate = tsString.substring(0, 10);
// If the date has changed, switch log files
if (!date.equals(tsDate)) {
synchronized (this) {
if (!date.equals(tsDate)) {
close();
date = tsDate;
open();
}
}
}
// Log this message, timestamped if necessary
if (writer != null) {
if (timestamp) {
writer.println(tsString + " " + msg);
} else {
writer.println(msg);
}
}
}
从上面的代码中可以看到,方法分为两部分,当日期改变的时候,会关闭一个文件,并创建一个新的文件记录日志;根据时间戳来判断,是否在消息前加上时间戳。
Tomcat的日志系统就说到这里了,如果要详细了解,建议去看《How tomcat works》原书。会有更多表达不出的感受。