1. 程式人生 > >how tomcat works讀書筆記 七 日誌記錄器

how tomcat works讀書筆記 七 日誌記錄器

錯誤輸出 new t rac .net ase code tor apache 格式

大家能夠松一口氣了,這個組件比較簡單,這一節和前面幾節想比,也簡單的多。



Logger接口

Tomcat中的日誌記錄器都必須實現org.apache.catalina.Logger接口。

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);
}


Logger定義了五種日誌記錄基本,當我們在調用log(String message, int verbosity)方法記錄日誌的時候,僅僅有傳進來的verbosity小於等於系統的默認值才會記錄。話說大家知道Integer.MIN_VALUE等於多少嗎?大概負的21億左右吧。setVerbosity與getVerbosity是幹什麽的還須要我說麽?

Tomcat的日誌記錄器

技術分享

LoggerBase類(抽象類)

它實現了Logger接口中除log(String message)方法外的其余方法;
在類中默認了日誌記錄級別為
protected int verbosity = ERROR;
可是我們能夠通過setVerbosity(int verbosity)來又一次設置記錄級別;
看看定義的接受日誌級別的兩個log方法
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);
}

SystemOutLogger類

看名字就知道,信息最後輸出到控制臺。

SysteErrLogger類

看名字就知道,它是錯誤輸出,信息仍在控制臺,只是是紅色的。

FileLogger類

看名字就知道,它是吧信息輸出的文件中。
只是詳細的來說,裏面還是有點說頭的,慢慢來。


首先FileLogger還實現了Lifecycle接口,因此它能夠像其它組件一樣被父組件所啟動。
在本節中FileLogger的start與stop方法事實上僅僅是改變了布爾值started而已,沒有做其它的,還有一方面,FileLogger的start與stop方法也並沒有被調用!
如今我們就看看怎麽給文件中寫信息。


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);
        System.out.println("tsString   "+tsString); //tsString   2014-10-20 15:25:27
        System.out.println("ts   "+ts);            //ts   2014-10-20 15:25:27.406
        System.out.println("tsDate   "+tsDate);        //tsDate   2014-10-20

        // 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);
            }
        }
    }


File默認是每一天一個新的文件,文件內格式就是日期+詳細信息(假設timestamp為true的話);
那close(),open()方法和writer屬性又是什麽呢?
   private void open() {

        // Create the directory if necessary
        File dir = new File(directory);
        if (!dir.isAbsolute())
            dir = new File(System.getProperty("catalina.base"), directory);  //至於catalina.base是什麽 一會再說
        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;
        }

    }

先檢查給定的文件夾是否存在,假設不存在新建一個;接著依據前綴,時間,後綴設定文件名稱;依據文件名稱填充writer對象。


    private void close() {

        if (writer == null)
            return;
        writer.flush();
        writer.close();
        writer = null;
        date = "";
    }

FileLogger中的date代表的就是當前的時間,當然關閉後為空。

應用程序


Bootstrap類

...
    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);
....

SimpleContext類

public synchronized void start() throws LifecycleException {
    log("starting Context");
    ........
    lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
    log("Context started");
  }
private void log(String message) {
    Logger logger = this.getLogger();
    if (logger!=null)
      logger.log(message);
  }



執行後在項目的webroot文件夾下就能夠看到FileLog_2014-10-20.txt文件;
每次執行,在文件裏都會多出例如以下的內容
2014-10-20 14:34:21 HttpConnector Opening server socket on all host IP addresses
2014-10-20 14:34:22 HttpConnector[8080] Starting background thread
2014-10-20 14:34:22 HttpProcessor[8080][0] Starting background thread
2014-10-20 14:34:22 HttpProcessor[8080][1] Starting background thread
2014-10-20 14:34:22 HttpProcessor[8080][2] Starting background thread
2014-10-20 14:34:22 HttpProcessor[8080][3] Starting background thread
2014-10-20 14:34:22 HttpProcessor[8080][4] Starting background thread
2014-10-20 14:34:22 starting Context
2014-10-20 14:34:22 Context started

how tomcat works讀書筆記 七 日誌記錄器