如今主流java項目通常使用slf4j+log4j的日誌方案,最近抽點時間掃了一下slf4j、log4j、logback的官方文檔,作個筆記。這篇比較不打算描述具體的配置方法,由於官方文檔已經講得很清楚了,而是描述一下核心的概念和方案。你們要對某個日誌方案作一個全面瞭解的話,最好的方式是看官方文檔,比baidu強不少。html
log4j官方文檔[https://logging.apache.org/log4j/2.x/index.html)(https://logging.apache.org/log4j/2.x/index.html)。
logback官方文檔https://logback.qos.ch/manual/index.htmljava
slf4j是一個日誌門面框架,用來解決不一樣的庫使用不一樣日誌方案的問題。slf4j創建了到全部主流日誌實現方案的橋接,假設我開發一個組件A,使用slf4j+(slf4j-brigdeto-log4)+log4j的方案來調試。當我發佈A的時候,是不帶這些日誌庫的,可是代碼裏面仍然會有打印日誌的語句。當某個用戶使用組件A時,他可使用任意日誌方案,只要採用slf4j+(slf4j-brigde-somelog)+somelog這個模式便可。在用戶那邊,組件A運行毫無障礙,日誌功能也很正常,只不過底層的日誌輸出再也不是log4j而是somelog。somelog能夠log4j,logback或其它,只要是slf4j支持的日誌方案就行。apache
所以使用這個方案,通常須要引入三個庫,依次是:slf4j-api(slf4j接口庫,應用代碼裏面直接使用);slf4j-bridgeto-somelog(slf4到somelog的橋接庫);somelog(somelog實現庫)。api
目前使用最多的日誌方案,從使用的角度,log4j2有3個核心概念:Logger,Appender,Layout。架構
logger表明一個日誌輸出對象,它是一個命名對象,而且多個logger經過名字能夠造成一個父子層級體系。
假若有一個logger A名字叫作"com",B的名字叫作"com.java",C名字叫作"com.java.controller",那麼C是B的後代,B是A的後代。
這樣當C經過logger.info輸出一條日誌時,這條日誌會在這個層級中往上傳遞;固然某個層級的logger可能會某種方式中斷這個傳遞,好比addtivity屬性。app
log4j必需要配置一個叫作root的logger,它是全部logger的根。框架
Appender表明日誌的輸出目的地,每一個logger必需要至少綁定一個Appender才能真正輸出日誌。Appender有不少類型,最多見的就是Console和FileAppender了,分別表明控制檯和本地文件。debug
表明日誌的格式化器,是Appender的子元素。在Appender決定要輸出一條日誌時,纔會使用格式化器格式化日誌爲一條文本。
這意味着,日誌的格式化被儘可能延遲,因此咱們輸出日誌要使用logger.info("event {} happend at {}",event,location)這樣的佔位符形式,而不是logger.info("event "+event+" happend at "+location)。前者在日誌被過濾的狀況下根本不會執行格式化。設計
level是logger的屬性,對日誌作一個有序的分類,從低到高依次是TRACE,DEBUG,INFO,WARN,ERROR,FATAL,若是level設置成ERROR,那麼只能輸出ERROR和FATAL,更低層次的日誌會被丟棄。調試
fiter是過濾器,能夠對日誌執行一些過濾操做,他能夠用在logger上,也能夠用在appender上,還能夠用在全局。
最後,若是配置看起來沒問題,可是運行卻不如預期,怎麼辦?能夠經過System.setProperty("log4j2.debug","true")讓log4j打印內部日誌(還有其餘手段,這裏拋磚引玉)。瞭解上面的這些知識點,再查查資料,複製粘貼一下,大多數狀況下,就能搞定日誌系統了。
logback是log4j同一個做者設計的,是用來取代後者的日誌方案。之因此要額外再設計一個logback,是由於slf4j和log4j經過橋接模式來工做,效率多少受點影響;logback則是直接基於sfl4j規範設置的,徹底不須要橋接。所以logback的架構、配置與log4j很是的相似。