一、概述
記得前些年項目中的日誌記錄,最開始用的是log4j。對一般的項目使用還算可以,肯定談不上很好,但還是可以勉強用的。後來有了log4j 2、commons logging、slf4j、logback等日誌框架。但slf4j不是具體的日誌實現框架,而是提供了常用的日誌接口,在使用的時候我們可以直接調用其接口,通過使用提供的,隱藏了日誌的具體實現。logback則提供了日誌記錄的功能。
二、logback介紹
logback的性能比log4j更好,在某此操作上,其性能得到了顯著的提升。log4j和logback源自同一個作者,但logback是log4j的升級,所以logback自然比log4j有很多優秀的地方。不過logback和log4j是比較相似的,如果你對log4j很熟悉或者使用過log4j,那對logback就能很快的應用起來。下面列出一部分logback的優點:
2.1,logback原生實現了slf4j的api
logback-classic實現了slf4j,但我們感覺不到logback-classic。如果我們要改用log4j會很容易,換相應的jar就好,不需要去更改slf4j的api實現。
2.2,支持xml、Groovy方式進行配置
2.3,支持配置文件中加入條件判斷
通過在配置文件中加入條件判斷,會增加靈活度,以處理不同的情況。比如通過<if>、<then>和<else>來配置日誌適用於不同的環境中,一個配置文件可以用到開發、測試、生產、演示環境中。當然也可以一個環境寫一個配置文件。
2.4,更爲強大的過濾器
比如在診斷某一問題時,需要打出日誌。對log4j只有降低日誌級別,但這樣打打印出很多不需要的日誌,同時也影響性能。對logback,可以繼續保持日誌級別,然後除掉某種特殊的情況。在使用中,可以針對不同用戶的登陸打印不同級別的日誌,而且配置也不復雜,可參考MDCFilter。
2.5,更充分的測試
到目前爲此,logback發展已經有些年了,經受住了廣大用戶的測試。
2.6,豐富的免費文檔
官網上有很多文檔,另外也有許多同行寫的一些使用說明文檔可供參考。
2.7,自動重載有變更的配置文件
當配置文件有了修改,logback-classic可以自動重新加載配置文件。掃描的過程快而且安全,它並不需要重新創建一個掃描線程。可通過<configuration>標籤的scan和scanPeriod來配置。
2.8,自動壓縮歷史日誌
RollingFileAppender在產生新日誌文件時,自動壓縮日誌。同時壓縮是個異步的過程,在壓縮的過程中,並不會影響應該的使用。
2.9,打印異常信息時自動包含package名稱及版本號
2.10,快速實現
logback的內核進行了重寫,在一些地方性能有明顯的提升,且初始化內存的加載也更小了。
2.11,自動去除舊的日誌文件
可以控制歷史日誌文件的保留時間,如果過期了會被清除。此功能涉及<maxHistory>標籤。
2.12,SiftingAppender
SiftingAppender可以根據給定的一個運行參數來分割日誌文件。比如可以區別日誌事件,跟進用戶的session,可根據要求一個用戶產生一個日誌文件。
2.13,Lilith
Lilith是log事件的觀察者,是logback的logging和AccessEvent查看工具,目錄已經更新到8.1以上了。和log4j的chainsaw類似。面Lilith還可處理大數量的log數據。
2.14,謹慎的模式和非常友好的恢復
在謹慎模式下,多個FileAppender實例跑在多個JVM下,能夠安全的寫進同一個日誌文件中。RollingFileAppender會有些限制。logback的FileAppender和它的子類包括RollingFileAppender能夠非常友好的從I/O異常中恢復。
三、logback配置介紹
3.1,logback配置文件結構
根節點爲<configuration>標籤,其子節點有Appender、Logger、Root。如下圖所示。
3.2,標籤與屬性解釋說明
下面對logback配置的部分標籤及標籤屬性進行解釋說明。
標籤或屬性名 | 解釋說明 |
<configuration> | 配置的根節點 |
--scan | 爲ture時,若配置文件屬性改變會被掃描並重新加載,默認爲true |
--scanPeriod | 監測配置文件是否有修改的時間間隔,若沒給出時間單位,默認單位爲毫秒;默認時間爲1分鐘;當scan="true"時生效 |
--debug | 爲true時,將打出logback的內部日誌信息,實時查看logback運行狀態;默認值爲false |
<contextName> | 上下文名稱,默認爲“default”,使用此標籤可設置爲其它名稱,用於區分不同應用程序的記錄;一旦設置不能修改 |
<appender> | <configuration>的子節點,負責寫日誌的組件,有name和class兩個必要屬性 |
-name | addender的名稱 |
-class | appender的全限定名,就是對應的某個具體的Appender類名,比如ConsoleAppender、FileAppender |
-append | 爲true地,日誌被追加到文件結尾,如果是flase,清空現存的文件,默認值爲true |
3.3,默認規則
日誌級別爲:TRACE < DEBUG < INFO < WARN < ERROR。
如果logback-test.xml和logback.xml都不存在,logback默認地調用BasicConfigurator,然後創建一個最小化的配置。此配置由一個關聯到根logger的ConsoleAppender組成,輸出結果使用模式爲%d{HH:mm:ss.SSS} [%thread] % -5level %logger{36} -%msg %n的PatternLayoutEncoder進行格式化。默認的級別爲DEBUG。
3.4,格式化參數說明
在日誌的pattern中,%d表示日期,%thread表示線程名,%-5level表示日誌級別從左顯示5個字符內容,%msg表示日誌消息內容,%n表示換行。它們一起配合使用對日誌的輸出內容進行格式化。下面舉例說明。
%d{yyyy-MM-dd HH:mm:ss.SSS},表示對時間進行按照yyyy-MM-dd HH:mm:ss.SSS格式進行格式化輸出,例如2017-07-07 12:07:07.222;
Conversion Pattern | Result |
---|---|
%d | 2006-10-20 14:06:49,812 |
%date | 2006-10-20 14:06:49,812 |
%date{ISO8601} | 2006-10-20 14:06:49,812 |
%thread和%-5level覺得沒什麼可以說的;
%logger{36}表示logger名稱最長爲36個字符,如果不夠36就是有多少就顯示多少;
Conversion specifier | Logger name | Result |
---|---|---|
%logger | mainPackage.sub.sample.Bar | mainPackage.sub.sample.Bar |
%logger{0} | mainPackage.sub.sample.Bar | Bar |
%logger{5} | mainPackage.sub.sample.Bar | m.s.s.Bar |
%logger{10} | mainPackage.sub.sample.Bar | m.s.s.Bar |
%logger{15} | mainPackage.sub.sample.Bar | m.s.sample.Bar |
%logger{16} | mainPackage.sub.sample.Bar | m.sub.sample.Bar |
%logger{26} | mainPackage.sub.sample.Bar | mainPackage.sub.sample.Bar |
%msg顯示的日誌的內容,%n換行,主要是用於方便查看日誌,如果所有的日誌都在一行,那真的看不下去了。
四、logback使用說明
4.1,具體使用說明
以下日誌配置是當前在做一個項目時配置的內容。
<?xml version="1.0" encoding="UTF-8"?> <configuration debug="true" scan="true" scanPeriod="60"> <!-- 設置日誌的存儲路徑,方便後面引用 --> <property name="log.dir" value="E:/data/logs/capabilityService" /> <property name="max.history" value="30" /> <!-- 活動文件的最大大小 --> <property name="max.file.size" value="100MB" /> <!-- 所有歸檔日誌文件的總大小/容量 --> <property name="total.size.cap" value="10G" /> <!-- 控制檯日誌的Appender --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!--<Encoding>UTF-8</Encoding>--> <!--<layout class="ch.qos.logback.classic.PatternLayout">--> <!--<!– 格式化輸出 –>--> <!--<pattern>[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger{36} -%msg%n</pattern>--> <!--</layout>--> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] [%thread] - %logger{50} -- %msg%n</pattern> </encoder> </appender> <!-- 錯誤日誌 輸出日誌文件--> <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 根據文件名稱的模式,設置按天回滾 --> <fileNamePattern>${log.dir}/com.worldStar-error-%d{yyyy-MM-dd}.log</fileNamePattern> <!-- 最大歷史天數,即保存多少天的日誌文件 --> <maxHistory>${max.history}</maxHistory> </rollingPolicy> <!-- 對記錄事件進行格式化 --> <encoder charset="UTF-8" class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>[%-5level] - %d{HH:mm:ss.SSS} [%thread] %logger{50} -- %msg%n</pattern> </encoder> </appender> <!-- 訪問日誌的Appender --> <appender name="ACCESS" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${log.dir}/com.worldStar-access-%d{yyyy-MM-dd}.log</fileNamePattern> <maxHistory>${max.history}</maxHistory> </rollingPolicy> <encoder charset="UTF-8" class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>[%-5level] - %d{HH:mm:ss.SSS} [%thread] %logger{36} -- %msg%n</pattern> </encoder> </appender> <!-- 監控日誌的Appender --> <appender name="MONITOR" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${log.dir}/com.worldStar-monitor-%d{yyyy-MM-dd}.log</fileNamePattern> <maxHistory>${max.history}</maxHistory> </rollingPolicy> <encoder charset="UTF-8" class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>[%-5level] - %d{HH:mm:ss.SSS} [%thread] %logger{36} -- %msg%n</pattern> </encoder> </appender> <!-- 緩存日誌的Appender --> <appender name="CACHE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 按天回滾 --> <fileNamePattern>${log.dir}/com.worldStar-cache-%d{yyyy-MM-dd}.log</fileNamePattern> <maxHistory>${max.history}</maxHistory> </rollingPolicy> <encoder charset="UTF-8" class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>[%-5level] - %d{HH:mm:ss.SSS} [%thread] [%logger{36}] -- %msg%n</pattern> </encoder> </appender> <!-- 操作日誌的Appender --> <appender name="OPERATOR" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${log.dir}/com.worldStar-operator-%d{yyyy-MM-dd}.log</fileNamePattern> <maxHistory>${max.history}</maxHistory> </rollingPolicy> <encoder charset="UTF-8" class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>[%-5level] - %d{HH:mm:ss.SSS} [%thread] [%logger{36} -- %msg%n]</pattern> </encoder> </appender> <!-- springframework的日誌 --> <logger name="org.springframework" level="ERROR" /> <!-- apache的日誌 --> <logger name="org.apache" level="ERROR" /> <!-- 這裏addivitity要爲false,否則STDOUT的日誌也會達到ERROR裏 --> <!-- 監控日誌 --> <logger name="WORLDSTAR_MONITOR" additivity="false" level="INFO"> <appender-ref ref="MONITOR" /> </logger> <!-- 錯誤日誌 --> <logger name="WORLDSTAR_ERROR" additivity="false" level="DEBUG"> <appender-ref ref="ERROR" /> </logger> <!-- 訪問日誌 --> <logger name="WORLDSTAR_ACCESS" addivitity="false" level="INFO"> <appender-ref ref="ACCESS" /> </logger> <!-- 緩存日誌 --> <logger name="WORLDSTAR_CACHE" additivity="false" level="INFO"> <appender-ref ref="CACHE" /> </logger> <!-- 操作日誌 --> <logger name="WORLDSTAR_OPERATOR" additivity="false" level="INFO"> <appender-ref ref="OPERATOR" /> </logger> <root level="DEBUG"> <appender-ref ref="STDOUT" /> </root> </configuration>
addivitity用於children-logger是否使用root-logger配置的appender進行輸出。爲false時表示只用當前logger的appender,爲true時表示當前logger的appender-ref和root-logger的appender-ref都有效。
4.2,總結
logback使用過程中,要配置輸出日誌的添加器Appender、日誌打印的子節點logger和根節點root。日誌的輸出是從子節點開始,如果子節點有輸出內容則直接輸入到根節點,如果子節點沒有輸出內容,則判斷logger節點的additivity,是否向上級Root傳遞,如果傳遞的話則使用Root的輸出,否則就不打印日誌。
五、第三方工具、擴展
5.1,Lilith
這個在文章的上面提到過,是logback的Logging和AccessEvent查看器。
5.2,Logback-akka
由幾個基於akka的logback實用程序組成,包括ActorAppender,HoptoadActorAppender和Logstash redis appender。
5.3,Logback-android
可以將logback強大的功能應用在Android上。
5.4,Simpledb-appender
Logback Appender可以寫入Amazon SimpleDB。
5.5,logback-configuration
一個服務層(使用Spring)和一個REST風格的接口,它提供了以下方法:添加或更新日誌,解析日誌文件,解析logback配置文件,並上載logback配置文件並重新加載它。
5.6,Logback-gelf
可以通過GELF消息將消息記錄到Graylog2服務器。
5.7,Logback-testing
TestNG Reporter的logback appender。