我的目標是授人以漁,而不是授人以魚,我相信你仔細看完這篇文章,玩轉log4j不成問題 先來一個log4j最簡單的例子 在類路徑(src目錄下)創建log4j的配置文件log4j.properties,裡面的內容 運行一下,你會看到控制台有輸出,這就是一個最簡單的log4j配置的例子 來解釋一下這3行 ...
我的目標是授人以漁,而不是授人以魚,我相信你仔細看完這篇文章,玩轉log4j不成問題
先來一個log4j最簡單的例子
public class MyApp {
static Logger logger = Logger.getLogger(MyApp.class.getName());
public static void main(String[] args) {
logger.info("Entering application.");
Bar bar = new Bar();
bar.doIt();
logger.info("Exiting application.");
}
}
public class Bar {
static Logger logger = Logger.getLogger(Bar.class);
public void doIt() {
logger.debug("Did it again!");
}
}
在類路徑(src目錄下)創建log4j的配置文件log4j.properties,裡面的內容
log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.SimpleLayout
運行一下,你會看到控制台有輸出,這就是一個最簡單的log4j配置的例子
來解釋一下這3行配置
第一行:設置了根記錄器,值的格式為: 日誌級別, appender1, appender2...
log4j從低到高有這麼幾個日誌級別 DEBUG < INFO < WARN < ERROR < FATAL. 配置成DEBUG就會把所有級別的日誌都列印出來,反之配置成FATAL就只會列印FATAL級別的日誌
appender1, appender2就是第二行配置的
第二行:表示輸出到控制台,那除了ConsoleAppender就沒有別的Appender了麽,答案當然是有的,如圖
只要實現了Appender介面的都可以,所以可以看到第一行裡面的A1是在第二行定義的一個ConsoleAppender
第三行:log4j.appender.stdout一直到這裡都知道,這就是第二行的appender,那麼後面為什麼要接一個layout呢?
裡面是不是有一個屬性還是什麼呢?我們打開搜索一下,如圖
可以看到裡面有一個繼承自AppenderSkeleton的layout屬性,那麼A1後面接的layout就是這個layout屬性麽?
從第三行看到賦了一個SimpleLayout給layout,看起來一切合理,但是我想說的是第三行裡面的layout不是這個layout屬性,而是繼承自AppenderSkeleton裡面的setLayout方法的layout,我曾經在配置spring的時候也思考過這樣的問題,後來證明spring配置裡面的屬性配置是setXxx方法的Xxx,所以我99%的肯定這裡的layout是setLayout的layout,要想驗證也簡單,自己把ConsoleAppender到AppenderSkeleton所經過的類(並不是直接繼承)複製下來,然後把setLayout方法改一個名字,比如setLayout1,然後再用你自己的類配置,就知道這裡的layout到底還是layout1了,也就是到底是屬性還是setter方法裡面的,我沒有測試,如果有哪位同學測試得到了和我說的不一樣的結果,歡迎告訴我。
ConsoleAppender的setLayout是繼承自AppenderSkeleton的,而AppenderSkeleton是重寫的Appender介面裡面的setLayout方法,也就是所有的appender都需要配置layout
所有的appender都繼承自AppenderSkeleton,來看一下這個類裡面有哪些setter方法
可以看到有一個setThreshold方法,這個是配置日誌級別的,也就是說每個appender都可以配置自己的日誌級別,而不必使用統一的日誌級別
基於我的這個結果,也就是說只要類裡面有setter方法,都可以註入值,我們發現ConsoleAppender裡面有一個setTarget(String value)
所以這個target也是可以配置的,像這樣
log4j.appender.A1.target=System.out
填什麼值還是要看一下api,從api可以看出,target有2個值,分別是System.out和System.err,預設是System.out
target表示輸出的目標,System.err只輸出錯誤信息,System.out輸出所有信息
如果第三行配置成下麵的
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
表示可以自定義的靈活佈局,裡面有一個setConversionPattern方法,傳入轉換模式就可以得到自定義的輸出佈局,可以看到setConversionPattern這個方法是PatternLayout獨有的,其他的layout沒有的,這是因為其他的layout的佈局是固定的
如第三行的SimpleLayout表示簡單佈局,僅列印日誌級別和日誌信息,如DEBUG - Hello world
而PatternLayout的佈局是需要自己定義的,所以需要加上一行轉換預設的配置,比如可以這樣配置
log4j.appender.A1.Layout.conversionPattern=%d{ABSOLUTE} %-4p [%t] %c{5} - %m%n
這一行表示什麼意思呢?我們來看一下,可以看一下官方的說明
http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html
不懂的自行有道翻譯,還是翻譯的不錯的,至少我是翻譯的,哈哈哈。。。
我取一些講一下,每個轉換字元都要用%開頭,而且是區分大小寫的,不要弄錯了
%c 類的全路徑,可以加參數使用,如果類路徑是a.b.c.Test,那麼%c{2}得到的結果是c.Test,表示只保留後面的2項
%C 和%c的作用是一樣的,而且性能較差,所以我不知道為什麼還要弄這個出來
%d 格式化時間,可以這樣用%d{HH:mm:ss,SSS} or %d{dd MMM yyyy HH:mm:ss,SSS},這樣是最終調用了SimpleDateFormat,
這樣性能不好,所以應該這樣用%d{ISO8601} or %d{ABSOLUTE} or %d{DATE},這3種出來的格式分別是
%d{ISO8601}: 2018-03-26 17:18:38,207
%d{ABSOLUTE}: 17:19:06,630
%d{DATE}: 26 三月 2018 17:13:12,056
%F 發出日誌請求的文件名, 不推薦使用
%l 位置信息,不推薦使用
%m 日誌信息
%n 換行
%p 日誌級別
%r 從佈局構建到日誌記錄事件創建的毫秒數
%t 線程
%x 用於輸出與生成日誌事件的線程關聯的NDC(嵌套診斷上下文)
%% 輸出一個%
敲黑板,敲黑板。重要的來了
在%和轉換字元之間還可以配置對齊方式、最小字元寬度和最大字元寬度
預設右對齊,負號-表示左對齊
數字指定最小字元寬度,如果小於最小字元寬度則依據對齊規則在左邊或右邊添加空格
. 數字(點號接數字)表示最大字元寬度,如果大於最大字元寬度,則保留後面的最大字元寬度的字元
看幾個例子
%20c 右對齊最小寬度20的類路徑
%-20c 左對齊最小寬度20的類路徑
%.30c 最大寬度為30的類路徑,因為總是沒有多餘的空間,所以沒有對齊方式,表現出來的對齊方式是左對齊
%20.30c 右對齊最小寬度為20,最大寬度為30的類路徑
%-20.30c 左對齊最小寬度為20,最大寬度為30的類路徑
現在知道上面例子中%-4p的意思了:左對齊最小寬度為4的日誌級別
如果想讓特定的包下的類或特定的類輸出指定級別的日誌,可以像這樣配置
log4j.logger.com.foo=WARN
說明:log4j.logger.是固定的
com.foo是你要指定日誌級別的包或類,這樣com.foo包下的所有類(或com.foo類)的日誌級別就是WARN,其他包或類不受影響
來看一下其他常用的Appener
DailyRollingFileAppender(日常翻滾文件Appender):以時間來翻滾的appender
就把裡面的一個setDatePattern方法講一下,其他的setter方法就不說了,可以直接配置的
DailyRollingFileAppender預設是每天創建一個新的日誌文件,通過setDatePattern方法可以設置為每個月,每個星期,每個小時設置每分鐘創建一個新的日誌文件
RollingFileAppender(翻滾文件appender):以日誌文件大小來翻滾
預設翻滾大小是10M,翻滾個數是1個,這都是可以通過裡面裡面的setter方法來設置的,就不再多說了
最後給一個2個appender的配置文件示例
log4j.rootLogger=DEBUG, A1, A2
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.SimpleLayout
log4j.appender.A2=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A2.datePattern='.'yyyy-MM-dd HH-mm
log4j.appender.A2.file=test.log
log4j.appender.A2.encoding=utf-8
#log4j.appender.A2.append=true
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.conversionPattern=%r [%t] %-5p (%.30c) [%x] - %m%n