009_logback本地Appender
一. Appender接口
1. 什么是Appender?
1.1. Appender是負責(zé)寫記錄事件的組件。Appender必須實現(xiàn)接口"ch.qos.logback.core.Appender"。
2. Appender接口的重要方法
3. Appender接口里的多數(shù)方法都是getter和setting。值得注意的是doAppend()方法, 它唯一的參數(shù)是類型E的對象。類型E的實際類型視logback模塊的不同而不同。在logback-classic模塊里, E可能是"ILoggingEvent"類型; 在logback-access模塊里, E可能是"AccessEvent"類型。doAppend()方法也許是logback框架里最重要的方法, 它負責(zé)以適當(dāng)?shù)母袷綄⒂涗浭录敵龅胶线m的設(shè)備。
4. Appender接口擴展了FilterAttachable接口, 因此appender實例可被關(guān)聯(lián)一個或多個過濾器。
5. FilterAttachable接口的實現(xiàn)類FilterAttachableImpl
6. Appender是最終負責(zé)輸出記錄事件的組件。然而, 它們可以把實際格式化的任務(wù)委托給Layout或Encoder對象。每個layout/encoder都關(guān)聯(lián)到一個且僅一個appender。有些appender有內(nèi)置的或固定的事件格式, 因此它們不需要也沒有l(wèi)ayout/encoder。例如: SocketAppender在發(fā)送記錄事件之前只是簡單地對其進行序列化。
二. AppenderBase抽象類
1. 類ch.qos.logback.core.AppenderBase是實現(xiàn)了Appender接口的抽象類。AppenderBase提供所有appender共享的基本功能, 比如設(shè)置/獲取名字的方法, 其活動狀態(tài)和過濾器。AppenderBase是loback里繼承自appender的一個超類。盡管是抽象類, AppenderBase實際上實現(xiàn)了Appender接口的doAppend()方法。
2. AppenderBase抽象類doAppend方法實現(xiàn)
3. 這里的doAppend()方法的實現(xiàn)是同步的(synchronized), 確保不同線程對同一個appender的記錄是線程安全的。這里進行的同步并不總是合適的, logback帶了與AppenderBase非常相似的類ch.qos.logback.core.UnsynchronizedAppenderBase, 之后會討論它。
4. doAppend()方法做的第一件事就是檢查"guard"是否為true。如果是, 則立即退出方法。如果未設(shè)置"guard", 緊接下來的語句就把它設(shè)為true。"guard"確保doAppend()方法不會遞歸/重復(fù)調(diào)用自己。
5. 之后的語句里, 我們檢查"started"字段是否為true。如果不是, doAppend()會發(fā)出一條警告信息然后返回。換句話說, appender一旦關(guān)閉后, 就無法再向它寫入。Appender對象實現(xiàn)LifeCycle接口, 意味著它們實現(xiàn)了start()、stop()和isStarted()方法。對appender的所有屬性都設(shè)值后, Joran調(diào)用start()方法讓appender激活自己的屬性。
6. LifeCycle接口
7. 如果appender不能啟動或者已經(jīng)被停止, 則會通過logback的內(nèi)部狀態(tài)管理系統(tǒng)發(fā)出一條警告消息。嘗試幾次后, 為了避免內(nèi)部狀態(tài)系統(tǒng)被同一條警告消息所淹沒, doAppend()方法將停止發(fā)出這些警告消息。
8. 接著的if語句檢查關(guān)聯(lián)的過濾器的結(jié)果。根據(jù)過濾器鏈的判斷結(jié)果, 事件被拒絕或接受。如果過濾器鏈沒有結(jié)果, 則事件被默認(rèn)接受。
9. doAppend()方法然后調(diào)用派生類的append()方法, 此方法真正把事件增加到合適的設(shè)備。
10. 最后, 釋放guard, 允許下一個doAppend()調(diào)用。
三. UnsynchronizedAppenderBase抽象類
1. UnsynchronizedAppenderBase抽象類和AppenderBase抽象類最大的區(qū)別就是doAppend方法不是同步的
四. OutputStreamAppender類
1. OutputStreamAppender把事件添加到j(luò)ava.io.OutputStream。該類提供其他appender所需的基本服務(wù)。用戶通常不直接實例化OutputStreamAppender對象。由于java.io.OutputStream一般無法被方便地映射到字符串, 所以無法在配置文件里指定目標(biāo)OutputStream對象。簡而言之, 你不能在配置文件里配置OutputStreamAppender。但這不是說OutputStreamAppender沒有配置屬性。它的屬性如下。
2. OutputStreamAppender是另外三個appender的超類: ConsoleAppender、FileAppender及其直接子類RollingFileAppender。下圖演示了OutputStreamAppender和其子類的類圖。
五. ConsoleAppender類?
1. ConsoleAppender把事件添加到控制臺, 更準(zhǔn)確地說是System.out或System.err, 默認(rèn)為前者。
2. System.out和System.err都是java.io.PrintStream類型, 因此, 它們被包裹在有緩沖I/O操作的OutputStreamWriter里。
3. ConsoleAppender配置
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"><layout class="ch.qos.logback.classic.PatternLayout"><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></layout> </appender>六. FileAppender類
1. FileAppender是OutputStreamAppender的子類, 把記錄事件添加到文件。目標(biāo)文件通過File選項指定。如果文件已經(jīng)存在, 則根據(jù)Append屬性追加或清空文件。
2. FileAppender配置
<appender name="file" class="ch.qos.logback.core.FileAppender"><file>log/my.log</file><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder> </appender>七. RollingFileAppender類?
1. RollingFileAppender繼承FileAppender, 能夠滾動記錄文件。例如: RollingFileAppender能先記錄到文件"log.txt", 然后當(dāng)符合某個條件時, 變成記錄到其他文件。
2. RollingFileAppender有兩個與之互動的重要子組件。第一個是RollingPolicy負責(zé)滾動, 第二個是TriggeringPolicy決定是否以及何時進行滾動。所以RollingPolicy負責(zé)"什么", TriggeringPolicy負責(zé)"何時"。
3. 要想RollingFileAppender起作用, 必須同時設(shè)置RollingPolicy和TriggeringPolicy。不過, 如果RollingPolicy也實現(xiàn)了TriggeringPolicy接口, 那么只需要設(shè)置RollingPolicy。
4. 下面是RollingFileAppender的可用屬性
5. 滾動策略概述
5.1. RollingPolicy負責(zé)滾動步驟, 涉及文件移動和重命名。
5.2. RollingPolicy接口如下
5.3. rollover方法完成對當(dāng)前記錄文件的歸檔工作。
5.4. getActiveFileName()方法計算當(dāng)前記錄文件(寫實時記錄的地方)的文件名。
5.5. getCompressionMode()方法名所示, RollingPolicy也負責(zé)決定壓縮模式。
5.6. 最后, RollingPolicy通過setParent()方法得到一個對其父的引用。
6. FixedWindowRollingPolicy類
6.1. 當(dāng)發(fā)生滾動時, FixedWindowRollingPolicy根據(jù)固定窗口算法重命名文件。
6.2. 選項"fileNamePattern"代表歸檔(滾動)記錄文件的文件名模式。該選項是必需的, 且必需在模式的某處包含標(biāo)志"%i"。
6.3. 下面是FixedWindowRollingPolicy的可用屬性
6.4. 由于固定窗口滾動策略需要的文件重命名操作與窗口大小一樣多, 所以強烈建議不要使用太大的窗口大小。當(dāng)用戶指定過大的窗口大小時, 當(dāng)前的代碼會自動將窗口大小設(shè)為12。
讓我們來看固定窗口滾動策略的一個更具體的例子。假設(shè)"minIndex"是1, "maxIndex"是3, "fileNamePatter"是"foo%i.log"。
6.5. 使用FixedWindowRollingPolicy的RollingFileAppender的示例配置
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>log/my.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> <fileNamePattern>log/my.%i.log.zip</fileNamePattern> <minIndex>1</minIndex> <maxIndex>3</maxIndex> </rollingPolicy> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <maxFileSize>5MB</maxFileSize> </triggeringPolicy> <encoder> <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender>6.6. 例子
6.6.1. 新建一個名為LocalFwrp的Java項目, 同時添加相關(guān)jar包
6.6.2. 編輯Myfwrp.java
package com.zr.fwrp;import org.slf4j.Logger; import org.slf4j.LoggerFactory;public class Myfwrp {private static final Logger logger = LoggerFactory.getLogger(Myfwrp.class);public static void main(String[] args) {for(int i = 0; i < 100; i++) {logger.trace("我是一個跟蹤信息: " + i);logger.debug("我是一個測試信息: " + i);logger.info("我是一個日志信息: " + i);logger.warn("我是一個警告信息: " + i);logger.error("我是一個錯誤信息: " + i);try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}}} }6.6.3. 在src目錄下編輯logback.xml
<configuration debug="true"><appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"><layout class="ch.qos.logback.classic.PatternLayout"><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></layout></appender><appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>log/my.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> <fileNamePattern>log/my.%i.log.zip</fileNamePattern> <minIndex>1</minIndex> <maxIndex>12</maxIndex> </rollingPolicy> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <maxFileSize>10240</maxFileSize> </triggeringPolicy><encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender><root level="debug"><appender-ref ref="file" /><appender-ref ref="stdout" /></root></configuration>6.6.4. 運行項目, 生成了日志文件和壓縮包
7. TimeBasedRollingPolicy類?
7.1. TimeBasedRollingPolicy或許是最受流行的滾動策略。它根據(jù)時間來制定滾動策略, 例如根據(jù)日或月。TimeBasedRollingPolicy既負責(zé)滾動也負責(zé)觸發(fā)滾動。實際上, TimeBasedRollingPolicy同時實現(xiàn)了RollingPolicy接口和TriggeringPolicy接口。?
7.2. TimeBasedRollingPolicy有兩個屬性: 必需的"fileNamePattern"和可選的"maxHistory"。
7.3. 下面是fileNamePattern的部分值及其作用
7.4. TimeBasedRollingPolicy支持自動壓縮文件。如果"fileNamePattern"選項以".gz"或".zip"結(jié)尾, 就表示需要壓縮。
7.5. 屬性"fileNamePattern"有兩個目的。一是, logback計算滾動周期; 二是, 計算每個歸檔文件的名稱。注意, 可以為兩種不同的模式指定同一個周期。模式y(tǒng)yyy-MM和yyyy@MM都表示每月滾動, 但它們的歸檔文件名不同。
7.6. 通過設(shè)置"file"屬性, 你可以為活動記錄文件和歸檔記錄文件指定不同的位置。記錄輸出會被指向"file"屬性指定的文件, 所以活動文件的名字不會改變。然而, 如果沒有"file"屬性, 則活動文件的名字會根據(jù)"fileNamePattern"的值每隔一段時間就重新計算一次。
7.7. 屬性"maxHistory"控制被保留的歸檔文件的最大數(shù)量, 超出數(shù)量就刪除舊文件。例如, 假設(shè)每月滾動, 且maxHistory是6, 則只保留最近6個月的歸檔文件, 刪除之前的文件。注意當(dāng)刪除舊歸檔文件時, 那些為了歸檔而創(chuàng)建的目錄也會被刪除。
7.8. 出于某些技術(shù)原因, 滾動不是時鐘驅(qū)動, 而是按照記錄事件的到達時間。比如, 在2002年3月8日, 假設(shè)"fileNamePattern"是"yyyy-MM-dd"(每日滾動), 則午夜過后的第一個 記錄事件會觸發(fā)滾動。如果, 比如說直到0點23分47秒之前都沒有記錄事件, 那么滾動發(fā)生的實際時間是3月9日0點23分47秒, 而不是0點0分。因此, 根據(jù)事件到達的頻率, 滾動或許會被延時觸發(fā)。不過, 在某個時期內(nèi)產(chǎn)生的所有記錄事件都被輸出到劃分該時期的正確的文件, 從這個角度看, 雖然有延遲, 滾動算法仍然是正確的。
7.9. 下面是RollingFileAppender和TimeBasedRollingPolicy合作的例子
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>log/my.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>log/my.%d{yyyy-MM-dd}.log</fileNamePattern> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender>7.10. 下面是在prudent模式下, 使用TimeBasedRollingPolicy的RollingFileAppender的配置例子
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"> <prudent>true</prudent> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>my.%d{yyyy-MM-dd}.log</fileNamePattern> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender>7.11. 例子
7.11.1.?新建一個名為LocalTbrp的Java項目, 同時添加相關(guān)jar包
7.11.2.?編輯Mytbrp.java
package com.zr.fwrp;import org.slf4j.Logger; import org.slf4j.LoggerFactory;public class Mytbrp {private static final Logger logger = LoggerFactory.getLogger(Mytbrp.class);public static void main(String[] args) {for(int i = 0; i < 5; i++) {logger.trace("我是一個跟蹤信息: " + i);logger.debug("我是一個測試信息: " + i);logger.info("我是一個日志信息: " + i);logger.warn("我是一個警告信息: " + i);logger.error("我是一個錯誤信息: " + i);try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}}} }7.11.3.?在src目錄下編輯logback.xml
<configuration debug="true"><appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"><layout class="ch.qos.logback.classic.PatternLayout"><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></layout></appender><appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>log/my.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>log/my.%d{yyyy-MM-dd}.log</fileNamePattern> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender><root level="debug"><appender-ref ref="file" /><appender-ref ref="stdout" /></root></configuration>7.11.4.?運行項目, 同時調(diào)整系統(tǒng)時間
8. 基于大小和時間的歸檔
8.1. 有時你也許想按照日期進行歸檔的同時限制每個記錄文件的大小, 特別是當(dāng)后處理工具對記錄文件大小有限制時。Logback為此提供了SizeAndTimeBasedFNATP, 它是TimeBasedRollingPolicy的子組件, FNATP代表"文件命名和觸發(fā)策略"。
8.2. 下面的例子演示了基于大小和時間的記錄文件歸檔
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>log/my.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>log/my.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <encoder> <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender>8.3. 注意"%d"后面的"%i"。在當(dāng)前時間周期結(jié)束之前, 每當(dāng)當(dāng)前記錄文件達到"maxFileSize"時, 就會用遞增索引歸檔, 索引從0開始。
8.4. 基于大小和時間的歸檔支持刪除舊歸檔文件。你需要用"maxHistory"屬性指定要保留的周期的數(shù)量。當(dāng)程序停止并重啟時, 記錄會從正確的位置繼續(xù), 即當(dāng)前周期的最大索引。
9. 觸發(fā)策略概述
9.1. TriggeringPolicy負責(zé)指示RollingFileAppender在什么時候滾動。
9.2. TriggeringPolicy接口只有一個方法
9.3. isTriggeringEvent()方法有兩個參數(shù), 一個是歸檔文件, 一個是當(dāng)前正被處理的記錄事件。該方法的具體實現(xiàn)根據(jù)這兩個參數(shù)來決定是否進行滾動。
10. SizeBasedTriggeringPolicy類
10.1. 查看當(dāng)前活動文件的大小。如果超過指定大小SizeBasedTriggeringPolicy會告訴RollingFileAppender去觸發(fā)當(dāng)前活動文件的滾動。
10.2. SizeBasedTriggeringPolicy只有一個參數(shù)maxFileSize, 默認(rèn)值是10MB。
10.3. 根據(jù)數(shù)字后面不同的后綴, "maxFileSize"可以是bytes、KB、MB或GB。比如: 5000000, 5000KB、5MB和2GB都是合法值, 且前三個等價(為bytes的時候不要帶單位)。
10.4. 下面是RollingFileAppender與SizeBasedTriggeringPolicy合作的配置例子, 當(dāng)記錄文件的大小超過5MB后, 會觸發(fā)滾動。
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>my.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"><fileNamePattern>my.%i.log.zip</fileNamePattern> <minIndex>1</minIndex> <maxIndex>3</maxIndex> </rollingPolicy> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <maxFileSize>5MB</maxFileSize> </triggeringPolicy> <encoder> <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender>?
總結(jié)
以上是生活随笔為你收集整理的009_logback本地Appender的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 016_Spring中电子邮件
- 下一篇: 010_logback中的SocketA