12,tomcat日志处理
日志系统是一个记录信息的组件。在Catalina中,日志系统是一个相对简单的跟容器相关联的组件。Tomcat在org.apache.catalina.logger包中提供了多个不同的日志系统
Logger接口
一个日志系统必须实现org.apache.catalina.Logger接口
public interface Logger {
// ----------------------------------------------------- Manifest Constants
/**
* Verbosity level constants for log messages that may be filtered
* by the underlying logger.
*/
public static final int FATAL = Integer.MIN_VALUE;
public static final int ERROR = 1;
public static final int WARNING = 2;
public static final int INFORMATION = 3;
public static final int DEBUG = 4;
// ------------------------------------------------------------- Properties
/**
* Return the Container with which this Logger has been associated.
*/
public Container getContainer();
/**
* Set the Container with which this Logger has been associated.
*
* @param container The associated Container
*/
public void setContainer(Container container);
/**
* Return descriptive information about this Logger implementation and
* the corresponding version number, in the format
* <code><description>/<version></code>.
*/
public String getInfo();
/**
* Return the verbosity level of this logger.Messages logged with a
* higher verbosity than this level will be silently ignored.
*/
public int getVerbosity();
/**
* Set the verbosity level of this logger.Messages logged with a
* higher verbosity than this level will be silently ignored.
*
* @param verbosity The new verbosity level
*/
public void setVerbosity(int verbosity);
// --------------------------------------------------------- Public Methods
/**
* Add a property change listener to this component.
*
* @param listener The listener to add
*/
public void addPropertyChangeListener(PropertyChangeListener listener);
/**
* Writes the specified message to a servlet log file, usually an event
* log.The name and type of the servlet log is specific to the
* servlet container.This message will be logged unconditionally.
*
* @param message A <code>String</code> specifying the message to be
*written to the log file
*/
public void log(String message);
/**
* Writes the specified exception, and message, to a servlet log file.
* The implementation of this method should call
* <code>log(msg, exception)</code> instead.This method is deprecated
* in the ServletContext interface, but not deprecated here to avoid
* many useless compiler warnings.This message will be logged
* unconditionally.
*
* @param exception An <code>Exception</code> to be reported
* @param msg The associated message string
*/
public void log(Exception exception, String msg);
/**
* Writes an explanatory message and a stack trace for a given
* <code>Throwable</code> exception to the servlet log file.The name
* and type of the servlet log file is specific to the servlet container,
* usually an event log.This message will be logged unconditionally.
*
* @param message A <code>String</code> that describes the error or
*exception
* @param throwable The <code>Throwable</code> error or exception
*/
public void log(String message, Throwable throwable);
/**
* Writes the specified message to the servlet log file, usually an event
* log, if the logger is set to a verbosity level equal to or higher than
* the specified value for this message.
*
* @param message A <code>String</code> specifying the message to be
*written to the log file
* @param verbosity Verbosity level of this message
*/
public void log(String message, int verbosity);
/**
* Writes the specified message and exception to the servlet log file,
* usually an event log, if the logger is set to a verbosity level equal
* to or higher than the specified value for this message.
*
* @param message A <code>String</code> that describes the error or
*exception
* @param throwable The <code>Throwable</code> error or exception
* @param verbosity Verbosity level of this message
*/
public void log(String message, Throwable throwable, int verbosity);
/**
* Remove a property change listener from this component.
*
* @param listener The listener to remove
*/
public void removePropertyChangeListener(PropertyChangeListener listener);
}
日志接口提供了日志系统要实现的方法,最简单的方法是接受一个字符串并将其记录,
最后两个方法会接受一个冗余级别(verbosity level),如果传递的数字低于该类的实例设置的冗余级别,就将信息记录下来,否则就忽略信息。
静态变量定义了五个冗余级别:FATAL, ERROR, WARNING, INFORMATION,和 DEBUG。getVerbosity和setVerbosity分别用来获得和设置冗余级别。
日志接口还有getContainer 和 setContainer方法用来将日志系统跟容器关联起来
Tomcat日志系统
Tomcat提供了三种日志系统,它们分别是FileLogger, SystemErrLogger, 和 SystemOutLogger。
都继承了org.apache.catalina.logger.LoggerBase类
LoggerBase类
LoggerBase类是一个抽象类,它实现了Logger接口中除log(String msg)之外的所有方法。
public abstract void log(String msg);
该方法需要在子类进行覆盖(overload),所有的其他的log方法都调用了该方法
SystemOutLogger类
SystemOutLogger作为LoggerBase的子类提供了log(String message)方法的实现
每一个收到的信息都被传递给System.out.println
public class SystemOutLogger extends LoggerBase {
protected static final String info = "org.apache.catalina.logger.SystemOutLogger/1.0";
public void log(String msg) {
System.out.println(msg);
}
}
SystemErrLogger类
public class SystemErrLogger extends LoggerBase {
protected static final String info = "org.apache.catalina.logger.SystemErrLogger/1.0";
public void log(String msg) {
System.err.println(msg);
}
}
FileLogger类
FileLogger是LoggerBase类中最复杂的
它将从关联容器收到的信息写到文件中,每个信息可以选择性的加上时间戳。
在第一次实例化的时候,该类的实例会创建一个文件,该文件的名字带有日期信息。
如果日期改变了,它会创建一个新的文件并把信息写在里面。
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);
}
}
}
log方法接受一个消息并把消息写到日志文件中。
在FileLogger实例的生命周期中,log方法可以打开或关闭多个日志文件。
写日志的方法
private void open() {
// Create the directory if necessary
File dir = new File(directory);
if (!dir.isAbsolute())
dir = new File(System.getProperty("catalina.base"), directory);
dir.mkdirs();
// Open the current log file
try {
String pathname = dir.getAbsolutePath() + File.separator +
prefix + date + suffix;
writer = new PrintWriter(new FileWriter(pathname, true), true);
} catch (IOException e) {
writer = null;
}
}
open方法首先应该创建日志的目录是否存在,如果目录不存在,则首先创建目录
Close方法清空PrintWriter变量writer,然后关闭PrintWriter并将writer设置为null
private void close() {
if (writer == null)
return;
writer.flush();
writer.close();
writer = null;
date = "";
}
页:
[1]