Java Logging之JUL系列——Filter

本文介紹日誌過濾器(Filter),顧名思義,Filter就是用來對輸出的日誌信息進行過濾作用的,我們可以根據很多維度來對日誌信息進行過濾,比如只輸出message中包含某段文本信息的日誌,或者只輸出某個方法中記錄的日誌等等。具體能根據哪些維度來過濾我們後面介紹LogRecord的時候再回顧一下。本文我只舉兩個例子,一個是根據具體文本信息進行過濾,另一個是根據方法名來過濾。

先簡單地說一下java.util.logging.LogRecord類,該類對日誌輸出的過程中涉及到的各種屬性進行封裝,可以理解爲通過LogRecord對象,我們可以獲取該條日誌的文本信息、日誌生成的時間戳、日誌來自於哪個類、日誌來自於哪個方法、日誌來自於哪個線程等等。日誌記錄器Logger對象的log方法中會將日誌信息包裝成一個LogRecord對象,最終會將該對象遞交給Handler進行實際的輸出操作,LogRecord對象可以理解爲是用來在JUL日誌組件當中進行數據傳遞的DTO(數據傳輸對象)。

Filter在JUL中是通過java.util.logging.Filter接口來表示的,該接口的聲明如下:

@FunctionalInterface
public interface Filter {

    /**
     * Check if a given log record should be published.
     * @param record  a LogRecord
     * @return true if the log record should be published.
     */
    public boolean isLoggable(LogRecord record);
}

該接口在java8中被聲明爲一個函數式接口,只有一個抽象方法:boolean isLoggable(LogRecord record),如果該方法返回true就表示不過濾掉該日誌,如果返回false就表示過濾掉該日誌,從而不進行輸出。在實際使用過程當中需要實現我們自己的過濾器。下面我們將實現兩個過濾器,一個是爲了構建和諧社會,對包含"Shit"信息的日誌進行過濾的shitFilter,另一個是隻對某個方法如"earnMoney"中記錄的日誌進行輸出的earnMoneyFilter。

首先我們看一下沒有Filter時的代碼以及輸出情況:

package cn.codecrazy.study;

import java.util.logging.Logger;

public class JavaLogging {
    private static final Logger logger = Logger.getLogger(JavaLogging.class.getName());
    public static void main(String[] args) {
        logger.info("Freedom");
        logger.info("Equality");
        logger.info("Justice");
        logger.info("Rule of Law");
        logger.info("Shit! too young too simple, sometimes naive");
        earnMoney();
    }

    private static void earnMoney() {
        logger.info("earn lots of money.");
    }
}

輸出如下:

八月 09, 2018 8:30:49 下午 cn.codecrazy.study.JavaLogging main
信息: Freedom
八月 09, 2018 8:30:49 下午 cn.codecrazy.study.JavaLogging main
信息: Equality
八月 09, 2018 8:30:49 下午 cn.codecrazy.study.JavaLogging main
信息: Justice
八月 09, 2018 8:30:49 下午 cn.codecrazy.study.JavaLogging main
信息: Rule of Law
八月 09, 2018 8:30:49 下午 cn.codecrazy.study.JavaLogging main
信息: Shit! too young too simple, sometimes naive
八月 09, 2018 8:30:49 下午 cn.codecrazy.study.JavaLogging earnMoney
信息: earn lots of money.

所有的信息都輸出來了,下面我們定義一個shitFilter來過濾掉"Shit! too young too simple, sometimes naive"這條日誌。我們可以採用lambda表達式來進行定義,當然,通過顯示地實現Filter接口的方式也是可以的,爲了簡單起見,我們直接用lambda表達式的語法。

private static final Logger logger = Logger.getLogger(JavaLogging.class.getName());
static {
    Filter shitFilter = logRecord -> !logRecord.getMessage().contains("Shit");
    logger.setFilter(shitFilter);
}

輸出爲:

八月 09, 2018 8:38:06 下午 cn.codecrazy.study.JavaLogging main
信息: Freedom
八月 09, 2018 8:38:06 下午 cn.codecrazy.study.JavaLogging main
信息: Equality
八月 09, 2018 8:38:06 下午 cn.codecrazy.study.JavaLogging main
信息: Justice
八月 09, 2018 8:38:06 下午 cn.codecrazy.study.JavaLogging main
信息: Rule of Law
八月 09, 2018 8:38:06 下午 cn.codecrazy.study.JavaLogging earnMoney
信息: earn lots of money.

可以看到包含"Shit"信息的日誌沒有被輸出來,達到了我們預期的過濾效果。同樣地,我們再實現一個過濾器,用來只輸出earnMoney方法中記錄的日誌,其他方法(如main方法)中記錄的日誌我們不進行輸出。Filter實現如下:

private static final Logger logger = Logger.getLogger(JavaLogging.class.getName());
static {
    Filter earnMoneyFilter = logRecord -> "earnMoney".equals(logRecord.getSourceMethodName());
    logger.setFilter(earnMoneyFilter);
}

輸出如下:

八月 09, 2018 8:41:09 下午 cn.codecrazy.study.JavaLogging earnMoney
信息: earn lots of money.

即只輸出了我們指定的方法中記錄的日誌信息。相信大家可能也看出來了,能根據哪些維度進行過濾關鍵是看LogRecord中對外提供了哪些信息。一旦我們對LogRecord中提供的信息有了更充分的瞭解,我們就能根據需要創建我們自己的Filter,從而更好地控制我們日誌的輸出。

關於LogRecord的詳細信息我們後面的文章再進行介紹。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章