1. 程式人生 > >Tomcat中日誌組件

Tomcat中日誌組件

rri .com date 新的 form ret syn exceptio lse

Tomcat日誌組件

AccessLog接口

public interface AccessLog {
    public void log(Request request, Response response, long time);
}

AccessLogAdapter

public class AccessLogAdapter implements AccessLog {
    private AccessLog[] logs;
    // 構造函數
    public AccessLogAdapter(AccessLog log) {
        Objects.requireNonNull(log);
        logs = new AccessLog[] { log };
    }
    // 添加新的 訪問日誌 AccessLog
    public void add(AccessLog log) {
        Objects.requireNonNull(log);
        AccessLog newArray[] = Arrays.copyOf(logs, logs.length + 1);
        newArray[newArray.length - 1] = log;
        logs = newArray;
    }
    // AccessLog 接口中的 log 方法,循環操作
    @Override
    public void log(Request request, Response response, long time) {
        for (AccessLog log: logs) {
            log.log(request, response, time);
        }
    }
}

Tomcat中日誌

技術分享圖片

? 默認在 server.xml 中配置了 AccessLogValve 。

<!-- server.xml Host 節點 -->
<Valve className="org.apache.catalina.valves.AccessLogValve"                                  directory="logs"
       suffix=".txt"
       prefix="localhost_access_log"
       pattern="%h %l %u %t &quot;%r&quot; %s %b" />
<!-- 
className=org.apache.catalina.valves.AccessLogValve
directory=logs               存儲位置
prefix                       文件前綴
suffix                       文件後綴
pattern                      輸出格式
-->
@Override
public void log(CharArrayWriter message) {
    System.out.println("log");
    rotate();

    /* In case something external rotated the file instead */
    if (checkExists) {
        synchronized (this) {
            if (currentLogFile != null && !currentLogFile.exists()) {
                try {
                    close(false);
                } catch (Throwable e) {
                    ExceptionUtils.handleThrowable(e);
                    log.info(sm.getString("accessLogValve.closeFail"), e);
                }

                /* Make sure date is correct */
                dateStamp = fileDateFormatter.format(
                    new Date(System.currentTimeMillis()));

                open();
            }
        }
    }

    // Log this message
    try {
        synchronized(this) {
            if (writer != null) {
                message.writeTo(writer);
                writer.println("");
                if (!buffered) {
                    writer.flush();
                }
            }
        }
    } catch (IOException ioe) {
        log.warn(sm.getString(
            "accessLogValve.writeFail", message.toString()), ioe);
    }
}

調用過程

// ContainerBase
@Override
public void logAccess(Request request, Response response, long time,
                      boolean useDefault) {
    boolean logged = false;
    // 獲取 註冊的 日誌組件
    AccessLog accessLog = getAccessLog();
    if (accessLog != null) {
        // 調用 適配器 log 方法
        accessLog.log(request, response, time);
        logged = true;
    }
    if (getParent() != null) {
        getParent().logAccess(request, response, time, 
                              (useDefault && !logged));
    }
}

@Override
public AccessLog getAccessLog() {
    // 默認 false
    if (accessLogScanComplete) {
        return accessLog;
    }
    // AccessLog 適配器
    AccessLogAdapter adapter = null;
    // 獲取所有註冊的 閥門 Valve
    Valve valves[] = getPipeline().getValves();
    for (Valve valve : valves) {
        // 判斷 Valve 的類型
        if (valve instanceof AccessLog) {
            if (adapter == null) {
                adapter = new AccessLogAdapter((AccessLog) valve);
            } else {
                adapter.add((AccessLog) valve);
            }
        }
    }
    if (adapter != null) {
        accessLog = adapter;
    }
    accessLogScanComplete = true;
    return accessLog;
}

自定義 AccessLog

在 server.xml 中 ,配置 Valve ,在解析 server.xml 會自動註冊。

public class WswAccessLogValve extends AbstractAccessLogValve {

    @Override
    protected void log(CharArrayWriter message) {
        System.out.println("access log");
    }
}
// message
//   ||
//   VV
// 0:0:0:0:0:0:0:1 - - [08/Dec/2018:23:47:07 +0800] "GET /tomcat/ HTTP/1.1" 200 139
<!-- server.xml Host 節點 -->
<Valve className="org.apache.catalina.valves.AccessLogValve"                      directory="logs" suffix=".txt"
       prefix="localhost_access_log"
       pattern="%h %l %u %t &quot;%r&quot; %s %b" />

<Valve className="org.apache.catalina.valves.WswAccessLogValve"/>
log                     // AccessLogValve 中輸出
access log      // WswAccessLogValve 中輸出

Tomcat中日誌組件