《How Tomcat Works》读书笔记(七)Logger

Logger是一个用来记录消息的tomcat组件并和一个container绑定在一起。
看一下它的接口定义:

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 log(String message);
    public void log(Exception exception, String msg);
    public void log(String message, Throwable throwable);
    //当传入的日志级别verbosity大于Logger被设置的级别时,message会被记录,否则被忽略。
    public void log(String message, int verbosity);
    public void log(String message, Throwable throwable, int verbosity);
    //属性改变监听器
    public void addPropertyChangeListener(PropertyChangeListener listener);
    public void removePropertyChangeListener(PropertyChangeListener listener);
}
Tomcat提供了三个Logger:FileLogger,SystemErrLogger,SystemOutLogger.
它们都继承了org.apache.catalina.logger.LoggerBase类.
在1.4中LoggerBase实现了org.apache.catalina.Logger接口.在1.5中还实现了Lifecycle接口.

LoggerBase是一个抽象类, 实现了Logger接口中除了log(String msg)外的所有方法。
public abstract class LoggerBase implements Logger {

    protected Container container = null;

    protected int debug = 0;
    //看起来是不是很熟悉?
    protected static final String info ="org.apache.catalina.logger.LoggerBase/1.0";

    protected PropertyChangeSupport support = new PropertyChangeSupport(this);
    //默认级别
    protected int verbosity = ERROR;

    public Container getContainer() {
        return (container);
    }
    public void setContainer(Container container) {
        Container oldContainer = this.container;
        this.container = container;
        support.firePropertyChange("container", oldContainer, this.container);
    }

    public void setVerbosityLevel(String verbosity) {
        if ("FATAL".equalsIgnoreCase(verbosity))
            this.verbosity = FATAL;
        else if ("ERROR".equalsIgnoreCase(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;
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        support.addPropertyChangeListener(listener);
    }

    public abstract void log(String msg);

    public void log(Exception exception, String msg) {
        log(msg, exception);
    }

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

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        support.removePropertyChangeListener(listener);
    }
    ......
}

SystemErrLogger,SystemOutLogger继承了LoggerBase,实现如其名,超级简单。

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);
    }
}
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相比上面两个复杂一些。它把从容器中接到的消息写到一个文件中。文件名和日期相关,当日期改变时,它会新建一个文件。
在1.4中FileLogger实现了Lifecycle接口,它可以像其他实现了Lifecycle接口的组件一样被启动/停止。
在1.5中 FileLogger的父类LoggerBase实现了 Lifecycle 接口。
public void start() throws LifecycleException {
    if (started)
        throw new LifecycleException (sm.getString("fileLogger.alreadyStarted"));
    lifecycle.fireLifecycleEvent(START_EVENT, null); started = true;
}
public void stop() throws LifecycleException {
    if (!started)
        throw new LifecycleException (sm.getString("fileLogger.notStarted"));
    lifecycle.fireLifecycleEvent(STOP__EVENT, null);
    started = false;
    close ();
}
public void log(String msg) {
    Timestamp ts = new Timestamp(System.currentTimeMillis());
    String tsString = ts.toString().substring(0, 19);
    String tsDate = tsString.substring(0, 10);
    //当日期改变时,创建被切换日志文件
    if (!date.equals(tsDate)) {
       synchronized (this) {
           if (!date.equals(tsDate)) {
               close();
               date = tsDate;
               //在指定的目录中创建一个新文件 
               open();
           }
       }
    }
    //记录消息,并附上时间
    if (writer != null) {
        if (timestamp) {
           writer.println(tsString + " " + msg);
        } else {
           writer.println(msg);
        }
    }
}
//在指定目录中创建一个新文件
private void open() {
    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);
    } catch (IOException e) {
        writer = null;
    }
}
private void close() {
    if (writer == null) return;
    writer.flush();
    writer.close();
    writer = null;
    date = "";
}

转载于:https://my.oschina.net/itjava/blog/109010

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值