Coder 爱翻译 How Tomcat Works 第七章
Chapter 7: Logger
日志是一个记录信息的组件。在Catalina中,它容器相关联的日志比其它组件相对简单得多。Tomcat在org.apache.catalina.logger包下提供多种类型的日志。
本章有三个部分:第一部分包括org.apache.catalina.Logger接口,所有的日志组件都必须实现这个接口。第二部分介绍了在Tomcat中的日志,第三章详细讲述了本章的应用程序使用Tomcat的日志。
The Logger Interface
一个日志必须实现org.apache.catalina.Logger接口:
Listing 7.1: The Logger interface package org.apache.catalina; import java.beans.PropertyChangeListener; public interface 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; public Container getContainer(); public void setContainer(Container container); public String getInfo(); public int getVerbosity(); public void setVerbosity(int verbosity); public void addPropertyChangeListener(PropertyChangeListener listener); public void log(String message); public void log(Exception exception, String msg); public void log(String message, Throwable throwable); public void log(String message, int verbosity); public void log(String message, Throwable throwable, int verbosity); public void removePropertyChangeListener(PropertyChangeListener listener); }
public abstract void log(String msg);
protected int verbosity = ERROR;
Listing 7.2: The setVerbosity method public void setVerbosityLevel(String verbosity) { if ("FATAL".equalsIgnoreCase(verbosity)) this.verbosity = FATAL; else if ("ERROR".egualsIgnoreCase(verbosity)) this.verbosity = ERROR; else if ("WARNING".equalsIgnoreCase(verbosity)) this.verbosity = WARNING; else if ("INFORMATION".equalsIgnoreCase(verbosity)) this.verbosity = INFORMATION; else if ("DEBUG".equalsIgnoreCase(verbosity)) this.verbosity = DEBUG; }
Listing 7.3: The log method overloads that accept verbosity public void log(String message, int verbosity) { if (this.verbosity >= verbosity) log(message); } public void log(String message, Throwable throwable, int verbosity) { if (this.verbosity >= verbosity) log(message, throwable); }
Listing 7.4: The SystemOutLogger Class package org.apache.catalina.logger; 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); } }
Listing 7.5: The SystemErrLogger class package org.apache.catalina.logger; 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); } }
Listing 7.6: The start and stop methods public void start() throws LifecycleException { // Validate and update our current component state if (started) throw new LifecycleException (sm.getString("fileLogger.alreadyStarted")); lifecycle.fireLifecycleEvent(START_EVENT, null); started = true; } public void stop() throws LifecycleException { // Validate and update our current component state if (!started) throw new LifecycleException (sm.getString("fileLogger.notStarted")); lifecycle.fireLifecycleEvent(STOP__EVENT, null); started = false; close (); }
Listing 7.7: The log method public void log(String msg) { // Construct the timestamp we will use, if reguested 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); } } }
Listing 7.8: The open method 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) { catch (IOException e) { writer = null; } }
File dir = new File(directory); if (!dir.isAbsolute()) dir = new File(System.getProperty("catalina.base"), directory); dir.mkdirs();
try ( String pathname = dir.getAbsolutePath() + File.separator + prefix + date + suffix;
writer = new PrintWriter(new FileWriter(pathname, true), true);
Listing 7.9: The close method private void close() { if (writer == null) return; writer.flush(); writer.close(); writer = null; date = ""; }
Timestamp ts = new Timestamp(System.currentTimeMillis());
yyyy-mm-dd hh:mm: SS.fffffffff
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); } }
Listing 7.10: The Bootstrap class package ex07.pyrmont.startup; import ex07.pyrmont.core.SimpleContext; import ex07.pyrmont.core.SimpleContextLifecycleListener; import ex07.pyrmont.core.SimpleContextMapper; import ex07.pyrmont.core.SimpleLoader; import ex07.pyrmont.core.SimpleWrapper; import org.apache.catalina.Connector; import org.apache.catalina.Context; import org.apache.catalina.Lifecycle; import org.apache.catalina.LifecycleListener; import org.apache.catalina.Loader; import org.apache.calalina.loggor.FileLogger; import org.apache.catalina.Mapper;import org.apache.catalina.Wrapper; import org.apache.catalina.connector.http.HttpConnector; public final class Bootstrap { public static void main(String[] args) { Connector connector = new HttpConnector(); Wrapper Wrapper1 = new SimpleWrapper(); Wrapper1.setName("Primitive"); Wrapper1.setServletClass("PrimitiveServlet"); Wrapper wrapper2 = new SimpleWrapper(); wrapper2.setName("Modern"); Wrapper2.setServletClass("ModernServlet"); Loader loader = new SimpleLoader(); Context context = new SimpleContext(); context.addChild(wrapper1); context.addChild(wrapper2); Mapper mapper = new SimpleContextMapper(); mapper.setProtocol("http"); LifecycleListener listener = new SimpleContextLifecycleListener(); ((Lifecycle) context).addLifecycleListener(listener); context.addMapper(mapper); context.setLoader(loader); // context.addServletMapping(pattern, name); context.addServletMapping("/Primitive", "Primitive"); context.addServletMapping("/Modern", "Modern");// ------ add logger -------- System.setProperty("catalina.base", System.getProperty("user.dir")); FileLogger logger = new FileLogger(); logger.setPrefix("FileLog_"); logger.setSuffix(".txt"); logger.setTimestamp(true); logger.setDirectory("webroot"); context.setLogger(logger); //-------------------------- connector.setContainer(context); try { connector.initialize(); ((Lifecycle) connector).start(); ((Lifecycle) context).start(); // make the application wait until we press a key. System.in.read(); ((Lifecycle) context).stop(); } catch (Exception e) { e.printStackTrace(); } } }