日志框架 Logback 官方手冊(第四章:Appenders)

以下內(nèi)容翻譯整理自logback官方手冊,地址:logback官方手冊


Appender 是什么承绸?

Logback將編寫日志事件的任務委托給稱為appenders的組件。Appenders必須實現(xiàn)ch.qos.logback.core.Appender接口。該接口的主要方法總結如下:

package ch.qos.logback.core;
  
import ch.qos.logback.core.spi.ContextAware;
import ch.qos.logback.core.spi.FilterAttachable;
import ch.qos.logback.core.spi.LifeCycle;

public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachable {

  public String getName();
  public void setName(String name);
  void doAppend(E event);
  
}

Appender接口中的大多數(shù)方法都是settergetter绞绒。只有doAppend()方法是例外的拦耐,它將一個類型為E的對象作為參數(shù)耕腾。E的實際類型將根據(jù)logback模塊的不同而有所不同。在logback-classic模塊中杀糯,E的類型是ILoggingEvent扫俺,在logback-access模塊中,E的類型是AccessEvent固翰。doAppend()方法是logback框架中最重要的方法狼纬。它負責將日志事件以適當?shù)母袷捷敵龅竭m當?shù)妮敵鲈O備。

Appenders是可以被命名的骂际。這確保了可以通過名稱引用它們疗琉,這是腳本配置中很重要的一個特性。Appender接口擴展了FilterAttachable接口歉铝,可以將一個或多個過濾器附加到一個appender實例盈简。過濾器將在下一章詳細討論。

Appenders負責最終輸出日志事件犯戏。但是送火,它們可以將日志事件的格式化委托給一個Layout或一個Encoder對象拳话。每個Layout/Encoder都與一個且僅與一個appender關聯(lián)先匪。有些appenders具有內(nèi)置或固定的事件格式,因此弃衍,它們既不需要也沒有Layout/Encoder呀非。例如,SocketAppender只會在通過網(wǎng)絡傳輸日志事件之前對它們進行序列化镜盯。

AppenderBase

ch.qos.logback.core.AppenderBase類是實現(xiàn)了Appender接口的一個抽象類岸裙。它提供了所有appenders共享的基礎功能,例如獲取或設置它們的名稱速缆、激活狀態(tài)降允、布局和過濾器的方法。它是logback自帶的所有appenders的超類艺糜。雖然是一個抽象類剧董,AppenderBase實際上實現(xiàn)了Appender接口中的doAppend()方法。下面是實現(xiàn)代碼:

public synchronized void doAppend(E eventObject) {

  // prevent re-entry.
  if (guard) {
    return;
  }

  try {
    guard = true;

    if (!this.started) {
      if (statusRepeatCount++ < ALLOWED_REPEATS) {
        addStatus(new WarnStatus(
            "Attempted to append to non started appender [" + name + "].",this));
      }
      return;
    }

    if (getFilterChainDecision(eventObject) == FilterReply.DENY) {
      return;
    }
    
    // ok, we now invoke the derived class's implementation of append
    this.append(eventObject);

  } finally {
    guard = false;
  }
}

這里實現(xiàn)的doAppend()是一個同步方法破停。因此翅楼,從不同的線程記錄到相同的appender是線程安全的。當線程(例如T)執(zhí)行doAppend()方法時真慢,其他線程隨后的調(diào)用將排隊毅臊,直到T離開doAppend()方法,從而確保Tappender的獨占訪問黑界。

由于這種同步并不總是合適的管嬉,所以logback又提供了一個ch.qos.logback.core.UnsynchronizedAppenderBase皂林,和AppenderBase類非常類似。為了簡潔起見宠蚂,我們在本文檔的其余部分只討論UnsynchronizedAppenderBase式撼。

doAppend()方法做的第一件事是檢查守衛(wèi)是否被設置為true。如果是求厕,則立即退出著隆。如果不是,則在下一個語句中將其設置為true呀癣。該保護確保doAppend()方法不會遞歸地調(diào)用自己美浦。假設一個在append()方法之外調(diào)用的組件想要記錄一些東西。它的調(diào)用可以直接指向剛才調(diào)用它的相同的追加器项栏,從而導致無限循環(huán)和堆棧溢出浦辨。

在接下來的語句中,我們檢查started字段是否為true沼沈。如果不是流酬,doAppend()將發(fā)送一個警告消息并返回。換句話說列另,一旦一個appender被關閉了芽腾,就不可能再對它進行寫入。Appender接口繼承了LifeCycle接口页衙,這意味著它的實現(xiàn)類也實現(xiàn)了start()摊滔、stop()isStarted()方法。設置完appender的所有屬性后店乐,Joranlogback的配置框架艰躺,它會調(diào)用start()方法來通知appender激活其屬性。根據(jù)其類型的不同眨八,如果某些屬性丟失或由于各種屬性之間的干擾腺兴,appender可能啟動失敗。例如廉侧,考慮到文件創(chuàng)建依賴于截斷模式页响,在Append選項的值被確定之前,FileAppender不能對它的File選項的值執(zhí)行操作伏穆。顯式激活步驟確保appender在其屬性的值被知道后對其進行操作拘泞。

如果appender無法啟動或已經(jīng)停止,將通過logback的內(nèi)部狀態(tài)管理系統(tǒng)發(fā)出警告消息枕扫。經(jīng)過多次嘗試陪腌,為了避免同一警告消息的副本充斥內(nèi)部狀態(tài)系統(tǒng),doAppend()方法將停止發(fā)出這些警告。

下一個if語句檢查附加過濾器的結果诗鸭。根據(jù)過濾器鏈產(chǎn)生的決策染簇,可以拒絕或顯式接受事件。在過濾器鏈沒有做出決定的情況下强岸,默認情況下接受事件锻弓。

然后doAppend()方法調(diào)用派生類的append()方法實現(xiàn)。此方法的實際工作是將執(zhí)行將事件附加到適當設備蝌箍。

最后青灼,釋放保護,以便允許隨后的請求調(diào)用doAppend()方法妓盲。

Logback-core

logback -core是構建其他logback模塊的基礎杂拨。提供了幾個定制的的appender。在接下來的幾節(jié)中悯衬,我們將介紹這幾個的appenders弹沽。

OutputStreamAppender

OutputStreamAppender追加事件到一個java.io.OutputStream。該類提供了其他appender構建的基礎筋粗。用戶通常不會直接實例化OutputStreamAppender對象策橘,因為一般來說java.io.OutputStream類型不能方便地映射到字符串属划,因為無法在配置腳本中指定目標OutputStream對象轧叽。簡單地說距帅,您不能從配置文件配置OutputStreamAppender萌腿。然而,這并不意味著OutputStreamAppender缺乏可配置屬性进统,下面將描述這些屬性。

屬性名稱 類型 描述
encoder Encoder 確定將事件寫入底層OutputStreamAppender的方式。之后會有專門的一章中介紹編碼器策州。
immediateFlush boolean 即時刷新的默認值是“true”。輸出流的立即刷新確保立即寫出日志事件宫仗,并且在應用程序在沒有正確關閉附加程序就退出時不會丟失日志事件够挂。另一方面,將此屬性設置為“false”可能會使日志吞吐量增加四倍(因人而異)藕夫。但是孽糖,如果在應用程序退出時沒有正確關閉appenders,那么尚未寫入磁盤的日志事件可能會丟失毅贮。

OutputStreamAppender是其他三個追加器的超類办悟,也就是ConsoleAppenderFileAppender滩褥、RollingFileAppender的超類病蛉。下圖展示了OutputStreamAppender及其子類的類圖。

ConsoleAppender

ConsoleAppender,顧名思義铺然,附加在控制臺俗孝,或者更準確地說是System.out或者System.err。前者是默認目標魄健。ConsoleAppender在用戶指定的編碼器的幫助下格式化事件赋铝。編碼器將在下一章中討論。這兩個System.outSystem.err的類型是java.io.PrintStream沽瘦,因此革骨,它們是被封裝在OutputStreamWriter中的緩沖 I/O 操作。

屬性名稱 類型 描述
encoder Encoder OutputStreamAppender的屬性介紹析恋。
target String 一個字符串值System.out或者System.err苛蒲,默認是System.out
withJansi boolean 默認情況下绿满,withJansi屬性被設置為false臂外。將withJansi設置為true將激活Jansi庫,該庫在Windows機器上提供對ANSI顏色代碼的支持喇颁。在一個Windows主機上漏健,如果這個屬性被設置為true,那么您應該在類路徑上添加“org.fusesource.jansi:jansi:1.9”橘霎。注意蔫浆,LinuxMac OS X等基于unix的操作系統(tǒng)默認支持ANSI顏色代碼。

下面是一個使用ConsoleAppender的示例配置姐叁。

<configuration>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!-- encoders are assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

FileAppender

FileAppenderOutputStreamAppender的一個子類瓦盛,追加日志事件到一個文件中,目標文件由File選項指定外潜。如果文件已經(jīng)存在原环,根據(jù)append屬性的值,要么被追加处窥,要么被截斷嘱吗。

屬性名稱 類型 描述
append boolean 如果為true,事件將追加到現(xiàn)有文件的末尾滔驾。如果appendfalse谒麦,則截斷任何現(xiàn)有文件。append選項默認為true哆致。
encoder Encoder OutputStreamAppender的屬性介紹绕德。
file String 要寫入的文件的名稱,如果文件不存在摊阀,就創(chuàng)建它耻蛇。在Windows平臺上剩瓶,文件c:\temp\test.log應該被寫為c:/temp/test.logc:\\temp\\test.logFile選項沒有默認值城丧。如果文件的父目錄不存在延曙,F(xiàn)ileAppender會自動創(chuàng)建它。
prudent boolean (1)在謹慎模式下亡哄,FileAppender將安全地寫入指定的文件枝缔,即使存在運行在不同JVM(可能運行在不同主機上)中的其他FileAppender實例。prudent的默認值為false蚊惯。謹慎模式可以與RollingFileAppender一起使用愿卸。謹慎模式意味著append屬性被自動設置為true(2) prudent更多地依賴于排他性文件鎖截型。實驗表明趴荸,文件鎖定的開銷大約是編寫日志事件開銷的三倍(x3)。在對本地硬盤上的文件進行寫操作時宦焦,如果關閉了謹慎模式发钝,寫一個日志事件大約需要10微秒。當謹慎模式打開時波闹,寫一個日志事件大約需要30微秒酝豪。(3)謹慎模式有效地序列化所有寫到同一文件的JVM之間的 I/O 操作。因此精堕,隨著爭用訪問文件的JVM數(shù)量的增加孵淘,每次 I/O 操作造成的延遲也會增加。只要 I/O 操作的總數(shù)低于每秒20個日志請求歹篓,對性能的影響應該可以忽略不計瘫证。如果每秒生成100個或更多 I/O 操作的應用程序可以看到對性能的影響,應該避免使用謹慎的模式庄撮。(4)當日志文件位于網(wǎng)絡文件系統(tǒng)中時背捌,謹慎模式的成本甚至更高。同樣重要的是重窟,網(wǎng)絡文件系統(tǒng)上的文件鎖有時可能存在嚴重偏差载萌,導致當前擁有鎖的進程在釋放鎖時立即重新獲得鎖惧财。因此巡扇,當一個進程占用日志文件鎖時,其他進程在等待鎖時超時垮衷,直到出現(xiàn)死鎖厅翔。(5)謹慎模式的影響高度依賴于網(wǎng)絡速度和操作系統(tǒng)實現(xiàn)細節(jié)。我們提供了一個非常小的應用程序 FileLockSimulator搀突,它可以幫助您模擬環(huán)境中謹慎模式的行為刀闷。

默認情況下,每個日志事件都會立即刷新到底層輸出流。從某種意義上說菌羽,如果應用程序在沒有正確關閉appenders的情況下退出灶泵,日志事件不會丟失觅彰,這種默認方法更安全。但是卒蘸,為了顯著提高日志吞吐量,您可能需要將immediateFlush屬性設置為false翻默。下面是FileAppender配置文件的一個例子:

<configuration>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>testFile.log</file>
    <append>true</append>
    <!-- 將immediateFlush設置為false缸沃,以獲得更高的日志吞吐量 -->
    <immediateFlush>true</immediateFlush>
    <!-- encoders are assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender>
        
  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

唯一命名的文件(按時間戳)

在應用程序開發(fā)階段或短期應用程序的情況下,例如修械,批量應用程序趾牧,最好在每次啟動新的應用程序時創(chuàng)建一個新的日志文件。在<timestamp>元素的幫助下肯污,這非常容易做到翘单。下面是一個例子:

<configuration>

  <!-- 插入一個格式為"yyyyMMdd'T'HHmmss"的時間戳"bySecond"到日志記錄器上下文。這個值將是可用于所有后續(xù)配置元素 -->
  <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <!-- use the previously created timestamp to create a uniquely
         named log file -->
    <file>log-${bySecond}.txt</file>
    <encoder>
      <pattern>%logger{35} - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

timestamp元素接受兩個強制屬性keydatePattern蹦渣,以及一個可選的timeReference屬性县恕。key屬性的值是時間戳名稱,后續(xù)配置元素可以通過引用該名稱將時間戳作為變量剂桥。datePattern屬性表示用于將當前時間轉換為字符串的日期格式忠烛。日期模式應該遵循SimpleDateFormat中定義的約定。timeReference屬性表示時間戳的時間引用权逗。默認值是當前時間美尸。然而,在某些情況下斟薇,可能需要使用上下文出生時間作為時間引用师坎。這可以通過將timeReference屬性設置為“contextBirth”來實現(xiàn)。如下所示:

<configuration>
  <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss" 
             timeReference="contextBirth"/>
  ...
</configuration>

RollingFileAppender

RollingFileAppender擴展了FileAppender堪滨,使其能夠滾動日志文件胯陋。例如,RollingFileAppender可以將日志記錄到一個名為log.txt的文件中袱箱,一旦滿足某個條件遏乔,就將其日志記錄目標更改為另一個文件。

RollingFileAppender有兩個重要的子組件发笔。第一個是RollingPolicy盟萨,負責滾動所需的操作。第二個子是TriggeringPolicy了讨,負責什么時候進行觸發(fā)滾動捻激。

要想發(fā)揮任何作用制轰,RollingFileAppender必須同時設置RollingPolicyTriggeringPolicy。但是胞谭,如果它的RollingPolicy也實現(xiàn)TriggeringPolicy接口垃杖,那么只需要顯式地指定前者。下面是RollingFileAppender的可用屬性:

屬性名稱 類型 描述
file String FileAppender屬性描述丈屹。
append boolean FileAppender屬性描述缩滨。
encoder Encoder OutputStreamAppender的屬性介紹。
rollingPolicy RollingPolicy 在發(fā)生翻轉時指示RollingFileAppender行為的組件泉瞻。請參閱下面的更多信息脉漏。
triggeringPolicy TriggeringPolicy 告訴RollingFileAppender何時激活翻轉過程。請參閱下面的更多信息袖牙。
prudent boolean 在謹慎模式下不支持FixedWindowRollingPolicy侧巨。謹慎模式下RollingFileAppender支持與TimeBasedRollingPolicy結合使用,有兩個限制:(1)在謹慎模式下鞭达,不支持也不允許文件壓縮司忱。(我們不能讓一個JVM在另一個JVM壓縮文件時寫入文件)(2)FileAppenderfile屬性必須保持空白。實際上畴蹭,大多數(shù)操作系統(tǒng)都不允許在打開另一個進程時重命名文件坦仍。詳情請參見FileAppender的屬性描述。

滾動策略概述

RollingPolicy負責包含文件移動和重命名的翻轉過程叨襟。RollingPolicy接口如下所示:

package ch.qos.logback.core.rolling;  

import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.spi.LifeCycle;

public interface RollingPolicy extends LifeCycle {

  public void rollover() throws RolloverFailure;
  public String getActiveFileName();
  public CompressionMode getCompressionMode();
  public void setParent(FileAppender appender);
}

rollover方法完成了歸檔當前日志文件所涉及的工作繁扎。調(diào)用getActiveFileName()方法來計算當前日志文件的文件名(寫入活動日志的地方)。如getCompressionMode方法所示糊闽,滾動策略還負責確定壓縮模式梳玫。最后,通過setParent方法向滾動策略提供對其父策略的引用右犹。

TimeBasedRollingPolicy

TimeBasedRollingPolicy可能是最流行的滾動策略提澎。它定義了一個基于時間的滾動策略,例如按天或按月念链∨渭桑基于時間的滾轉策略同時承擔滾轉和觸發(fā)滾轉的責任。實際上掂墓,TimeBasedTriggeringPolicy同時實現(xiàn)了RollingPolicyTriggeringPolicy接口谦纱。TimeBasedRollingPolicy的配置采用一個強制性的fileNamePattern屬性和幾個可選屬性。

屬性名稱 類型 描述
fileNamePattern String (1)強制的fileNamePattern屬性定義了滾動(存檔)日志文件的名稱梆暮。它的值應該由文件名組成服协,加上適當放置的%d轉換說明符。%d轉換說明符可以包含java.text.SimpleDateFormat指定的日期和時間模式啦粹。如果省略了日期和時間模式偿荷,會指定默認模式yyyy-MM-dd。滾轉周期由fileNamePattern的值推斷得出唠椭。(2)注意跳纳,可以設置或省略RollingFileAppender(TimeBasedRollingPolicy的父類)中的file屬性。通過設置包含FileAppenderfile屬性贪嫂,您可以解耦活動日志文件的位置和歸檔日志文件的位置寺庄。當前日志總是針對file屬性指定的文件。因此力崇,當前活動日志文件的名稱不會隨時間而更改斗塘。但是,如果您選擇忽略file屬性亮靴,那么活動文件將根據(jù)fileNamePattern的值為每個周期重新計算一次馍盟。下面的例子可以說明這一點。(3)時間和日期模式茧吊,%d{}中內(nèi)容遵循java.text.SimpleDateFormat約定贞岭。在fileNamePattern屬性或日期和時間模式中的任何位置上的正斜杠'/'或反斜杠'\'字符都將被解釋為目錄分隔符。(4)多個%d說明符:可以指定多個%d說明符搓侄,但其中只能有一個是主說明符瞄桨,即用于推斷滾動周期。所有其他令牌都必須通過傳遞“aux”參數(shù)標記為輔助性的(參見下面的示例)讶踪。多個%d說明符允許您在不同于滾轉期間的文件夾結構中組織歸檔文件芯侥。例如,下面所示的文件名模式按年/月組織日志文件夾乳讥,但每天在午夜時會將日志文件滾動按天生成一個文件筹麸。/var/log/%d{yyyy/MM, aux}/myapplication.%d{yyyy-MM-dd}.log(5)時區(qū):在某些情況下,您可能希望根據(jù)不同于主機時區(qū)的時鐘來滾動日志文件雏婶∥锔希可以在%d轉換說明符中按照日期和時間模式傳遞時區(qū)參數(shù)。例如:aFolder/test.%d{yyyy-MM-dd-HH, UTC}.log留晚。如果指定的時區(qū)標識符未知或拼寫錯誤酵紫,根據(jù)TimeZone.getTimeZone(String)方法規(guī)范指定為GMT時區(qū)。
maxHistory int 可選的maxHistory屬性控制要保存的最大歸檔文件數(shù)量错维,異步刪除舊文件奖地。例如,如果您指定每月滾動赋焕,并將maxHistory設置為6参歹,就會保存6個月的存檔文件,刪除6個月以上的文件隆判。注意犬庇,隨著舊歸檔日志文件的刪除僧界,為日志文件存檔而創(chuàng)建的任何文件夾都將被適當?shù)貏h除。
totalSizeCap int 可選的totalSizeCap屬性控制所有存檔文件的總大小臭挽。當超過總大小上限時捂襟,將異步刪除最舊的存檔。totalSizeCap屬性也需要設置maxHistory屬性欢峰。此外葬荷,總是先應用“最大歷史”限制,然后應用“總大小上限”限制纽帖。
cleanHistoryOnStart boolean 如果設置為true宠漩,將在appender啟動時執(zhí)行刪除存檔。默認情況下懊直,此屬性設置為false扒吁。

下面是一些fileNamePattern值,并解釋了它們的效果吹截。

fileNamePattern Rollover schedule Example
/wombat/foo.%d 每日翻轉(午夜)瘦陈。由于省略了%d說明符的時間和日期模式,所以設定了默認模式yyyy-MM-dd波俄,對應于每天的翻轉晨逝。 (1)文件屬性未設置:在2006年11月23日,日志輸出將進入文件/wombat/foo.2006-11-23懦铺。在午夜和24日剩下的時間里捉貌,日志輸出將定向到/wombat/foo.2006-11-24(2)文件屬性設置為/wombat/foo.txt:在2006年11月23日冬念,日志輸出將進入文件/wombat/foo.txt趁窃。午夜時分,foo.txt將更名為/wombat/foo.2006-11-23急前。將創(chuàng)建一個新的/wombat/foo.txt文件醒陆,11月24日剩余的日志輸出將定向到新的foo.txt
/wombat/%d{yyyy/MM}/foo.txt 每月初進行滾轉裆针。 (1)文件屬性未設置:在2006年10月刨摩,日志輸出將轉到/wombat/2006/10/foo.txt。在10月31日午夜之后世吨,在11月的剩余時間里澡刹,日志輸出將定向到/wombat/2006/11/foo.txt(2)文件屬性設置為/wombat/foo.txt:活動日志文件將一直是/wombat/foo.txt耘婚。在2006年10月期間罢浇,日志輸出轉到/wombat/foo.txt。10月31日午夜,/wombat/foo.txt將更名為/wombat/2006/10/foo.txt嚷闭。將創(chuàng)建一個新的/wombat/foo.txt文件攒岛,11月份剩余時間的日志輸出將放在該文件中。在11月30日午夜凌受,/wombat/foo.txt將更名為/wombat/2006/11/foo.txt等阵子。
/wombat/foo.%d{yyyy-ww}.log 在每個星期的第一天滾動思杯。注意胜蛉,一周的第一天取決于地區(qū)。 與之前的情況類似色乾,只是每一周的開始都會發(fā)生翻轉誊册。
/wombat/foo%d{yyyy-MM-dd_HH}.log 在每個小時的開始時候翻轉。 與以前的情況類似暖璧,只是每小時的開始都會發(fā)生翻轉案怯。
/wombat/foo%d{yyyy-MM-dd_HH-mm}.log 在每一分鐘的開始滾動。 與前面的情況類似澎办,只是每分鐘的開始都會發(fā)生翻轉嘲碱。
/wombat/foo%d{yyyy-MM-dd_HH-mm, UTC}.log 在每一分鐘的開始滾動。 與前面的情況類似局蚀,只是文件名將用UTC表示麦锯。
/foo/%d{yyyy-MM,aux}/%d.log 每天翻轉。檔案位于包含年和月的文件夾下琅绅。 在本例中扶欣,第一個%d說明符被標記為輔助的。第二個%d說明符省略了時間和日期模式千扶,是主要的料祠。因此,滾動將每天發(fā)生(%d的缺省值yyyy-MM-dd)澎羞,文件夾名稱將取決于年份和月份髓绽。例如,在2006年11月期間妆绞,存檔文件將全部放在/foo/2006-11/文件夾例如:/foo/2006-11/2006-11-14.log顺呕。

任何向前或向后斜杠字符都被解釋為文件夾(目錄)分隔符。任何需要的文件夾都將根據(jù)需要創(chuàng)建摆碉。因此塘匣,您可以輕松地將日志文件放在單獨的文件夾中。

TimeBasedRollingPolicy支持自動文件壓縮巷帝。如果fileNamePattern選項的值以.gz.zip結尾忌卤,則啟用此功能。

fileNamePattern Rollover schedule Example
/wombat/foo.%d.gz 每日滾動(在午夜)與自動GZIP壓縮存檔文件楞泼。 (1)文件屬性未設置:在2009年11月23日期間驰徊,日志輸出將轉到文件/wombat/foo.2009-11-23笤闯。然而,在午夜棍厂,該文件將被壓縮為/wombat/foo.2009-11-23.gz颗味。11月24日,日志輸出將定向到/wombat/folder/foo.2009-11-24牺弹,直到第二天它被滾動浦马。(2)文件屬性設置為/wombat/foo.txt:在2009年11月23日,日志輸出將進入文件/wombat/foo.txt张漂。在午夜晶默,該文件將被壓縮并重新命名為/wombat/foo.2009-11-23.gz。將創(chuàng)建一個新的/wombat/foo.txt文件航攒,11月24日剩余時間的日志輸出將放在該文件中磺陡。11月24日午夜,/wombat/foo.txt將被壓縮并改名為/wombat/foo.2009-11-24.gz漠畜,以此類推币他。

fileNamePattern有雙重用途。首先憔狞,通過研究模式蝴悉,logback計算請求的翻轉周期。其次躯喇,它計算每個存檔文件的名稱辫封。注意,兩種不同的模式可以指定相同的周期性。模式yyyy-MMyyyy@MM都指定了每月的滾動,盡管生成的歸檔文件將使用不同的名稱少欺。

通過設置file屬性,您可以解耦活動日志文件的位置和存檔日志文件的位置欣福。日志輸出將定向到file屬性指定的文件中。因此焦履,活動日志文件的名稱不會隨時間而更改拓劝。但是,如果您選擇忽略file屬性嘉裤,然后根據(jù)fileNamePattern的值為每個周期重新計算活動文件郑临。通過不設置file選項,您可以避免文件重命名錯誤屑宠,這些錯誤發(fā)生在存在外部文件句柄在滾轉期間引用日志文件時厢洞。

由于各種技術原因,滾動不是時鐘驅動的,而是取決于日志事件的到來躺翻。例如丧叽,在2002年3月8日,假設fileNamePattern設置為yyyy-MM-dd(每日翻轉)公你,午夜后第一個事件的到來將觸發(fā)翻轉踊淳。如果在午夜之后的23分47秒內(nèi)沒有日志記錄事件,那么翻轉實際上將發(fā)生在3月9日凌晨00:23'47陕靠,而不是凌晨0:00迂尝。因此,根據(jù)事件的到達率懦傍,可能會觸發(fā)一些延遲的滾動雹舀。但是芦劣,不管延遲如何粗俱,翻轉算法是正確的,因為在某個時間段內(nèi)生成的所有日志事件都將輸出到分隔該時間段的正確文件中虚吟。

下面是RollingFileAppenderTimeBasedRollingPolicy的示例配置寸认。

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logFile.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!-- 每日翻轉 -->
      <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>

      <!-- 將30天的歷史記錄限制在3GB的總大小 -->
      <maxHistory>30</maxHistory>
      <totalSizeCap>3GB</totalSizeCap>

    </rollingPolicy>

    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender> 

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

下一個配置示例演示了在謹慎模式下使用與TimeBasedRollingPolicy關聯(lián)的RollingFileAppender

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <!-- 支持多個JVM寫入同一個日志文件 -->
    <prudent>true</prudent>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
      <maxHistory>30</maxHistory> 
      <totalSizeCap>3GB</totalSizeCap>
    </rollingPolicy>

    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender> 

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

SizeAndTimeBasedRollingPolicy

有時串慰,您可能希望按日期歸檔文件偏塞,但同時限制每個日志文件的大小,特別是如果之后使用的處理工具對日志文件有大小限制時邦鲫。為了滿足這一需求灸叼,logback提供了SizeAndTimeBasedRollingPolicy

注意庆捺,TimeBasedRollingPolicy已經(jīng)允許限制歸檔日志文件的總體大小古今。如果只希望限制日志歸檔文件的總體大小,那么上面描述的TimeBasedRollingPolicy設置totalSizeCap屬性應該就夠用了滔以。

下面是一個示例配置文件捉腥,演示了基于時間和單個文件大小的日志文件歸檔。

<configuration>
  <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>mylog.txt</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
      <!-- 每日翻轉 -->
      <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
       <!-- 每個文件最多100MB你画,保存60天的歷史記錄抵碟,但總大小最多20GB -->
       <maxFileSize>100MB</maxFileSize>    
       <maxHistory>60</maxHistory>
       <totalSizeCap>20GB</totalSizeCap>
    </rollingPolicy>
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>


  <root level="DEBUG">
    <appender-ref ref="ROLLING" />
  </root>

</configuration>

注意%d之外的%i轉換符號。%i%d轉換符都是必需的坏匪,每次當前日志文件在當前時間段結束之前達到maxFileSize時拟逮,將使用一個遞增索引(從0開始)對其進行歸檔。

基于大小和時間的存檔支持刪除舊的存檔文件适滓。您需要使用maxHistory屬性指定要保存的周期數(shù)敦迄。當應用程序停止并重新啟動時,日志將繼續(xù)記錄在正確的位置,即當前期間的最大索引號颅崩。

1.1.7之前的版本中几于,這個文檔提到了一個名為SizeAndTimeBasedFNATP的組件。但是沿后,考慮到SizeAndTimeBasedFNATP配置結構比較簡單沿彭,我們不再記錄SizeAndTimeBasedFNATP。不過尖滚,使用SizeAndTimeBasedFNATP的早期配置文件將繼續(xù)正常工作喉刘。實際上,SizeAndTimeBasedRollingPolicy是用SizeAndTimeBasedFNATP子組件實現(xiàn)的漆弄。

FixedWindowRollingPolicy

當滾動時睦裳,FixedWindowRollingPolicy根據(jù)下面描述的固定窗口算法重命名文件。fileNamePattern選項表示歸檔(滾動)日志文件的文件名模式撼唾。此選項是必需的廉邑,并且必須在模式中包含整數(shù)令牌%i。下面是FixedWindowRollingPolicy的可用屬性倒谷。

屬性名稱 類型 描述
minIndex int 此選項表示窗口索引的下界蛛蒙。
maxIndex int 此選項表示窗口索引的上界。
fileNamePattern String 此選項表示在重命名日志文件時緊跟著FixedWindowRollingPolicy的模式渤愁。它必須包含字符串%i牵祟,該字符串表示將插入當前窗口索引值的位置。例如抖格,使用與最小值和最大值為13關聯(lián)的MyLogFile%i.log將生成名為MyLogFile1.log诺苹、MyLogFile2.logMyLogFile3.log的歸檔文件。注意雹拄,文件壓縮也是通過這個屬性指定的收奔。例如,fileNamePattern設置為MyLogFile%i.log.zip办桨,這意味著存檔文件必須使用zip格式進行壓縮筹淫;還支持gz格式。

由于固定窗口滾動策略需要的文件重命名操作與窗口大小一樣多呢撞,因此強烈建議不要使用較大的窗口大小损姜。當用戶指定較大的值時,當前實現(xiàn)將自動將窗口大小減小到20殊霞。

讓我們來看一個關于固定窗口翻轉策略的更具體的例子摧阅。假設minIndex設置為1maxIndex設置為3绷蹲,fileNamePattern屬性設置為foo%i.log棒卷。file屬性被設置為foo.log顾孽。

滾動數(shù)量 活動輸出目標 存檔日志文件 描述
0 foo.log - 還沒有發(fā)生滾轉,將日志返回到初始文件比规。
1 foo.log foo1.log 第一次翻轉若厚。foo.log被重命名為foo1.log。創(chuàng)建一個新的foo.log文件并成為活動輸出目標蜒什。
2 foo.log foo1.log, foo2.log 第二次翻轉测秸。將foo1.log重命名為foo2.logfoo.log被重命名為foo1.log灾常。創(chuàng)建一個新的foo.log文件并成為活動輸出目標霎冯。
3 foo.log foo1.log, foo2.log, foo3.log 第三個翻轉。將foo2.log重命名為foo3.log钞瀑。將foo1.log重命名為foo2.log沈撞。foo.log被重命名為foo1.log。創(chuàng)建一個新的foo.log文件并成為活動輸出目標雕什。
4 foo.log foo1.log, foo2.log, foo3.log 在這輪和隨后的幾輪中缠俺,滾動從刪除log.foo3.log開始。其他文件通過增加索引重命名监徘,如前面的步驟所示晋修。在接下來的滾動中,將一直有三個歸檔日志和一個活動日志文件凰盔。

下面的配置文件給出了一個配置RollingFileAppenderFixedWindowRollingPolicy的示例。注意倦春,File選項是強制性的户敬,即使它包含與fileNamePattern選項所傳遞的一些相同的信息。

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>test.log</file>

    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
      <fileNamePattern>tests.%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>
        
  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

觸發(fā)策略概述

TriggeringPolicy實現(xiàn)負責指示RollingFileAppender何時進行翻轉睁本。TriggeringPolicy接口只包含一個方法尿庐。

package ch.qos.logback.core.rolling;

import java.io.File;
import ch.qos.logback.core.spi.LifeCycle;

public interface TriggeringPolicy<E> extends LifeCycle {

  public boolean isTriggeringEvent(final File activeFile, final <E> event);
}

方法isTriggeringEvent()將活動文件和當前正在處理的日志事件作為參數(shù)。具體實現(xiàn)根據(jù)這些參數(shù)確定是否應該發(fā)生翻轉呢堰。

最廣泛使用的觸發(fā)策略是TimeBasedRollingPolicy抄瑟,它也是滾動策略的兩倍,前面已經(jīng)與其他滾動策略一起討論過枉疼。

SizeBasedTriggeringPolicy

SizeBasedTriggeringPolicy查看當前活動文件的大小皮假。如果它的大小超過指定的大小,它將向擁有的RollingFileAppender發(fā)出信號骂维,觸發(fā)現(xiàn)有活動文件的翻轉惹资。

SizeBasedTriggeringPolicy只接受一個參數(shù)maxFileSize,默認值為10MB航闺。

maxFileSize選項可以用字節(jié)褪测、千字節(jié)猴誊、兆字節(jié)或千兆字節(jié)來指定,方法是分別用KB侮措、MBGB作為數(shù)字值的后綴懈叹。例如,5000000分扎、5000KB项阴、5MB2GB都是有效值,前三個值是等價的笆包。

下面是一個帶有RollingFileAppender的示例配置环揽,它與SizeBasedTriggeringPolicy一起在日志文件達到5MB時觸發(fā)翻轉。

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>test.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
      <fileNamePattern>test.%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>
        
  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

Logback Classic

雖然日志事件在logback-core中是通用的庵佣,但在logback-classic中歉胶,它們始終是ILoggingEvent的實例。Logback-classic不過是一個專門處理ILoggingEvent實例的管道巴粪。

SocketAppender 和 SSLSocketAppender

到目前為止通今,所涉及的appenders只能記錄日志到本地資源。相反肛根,SocketAppender的設計目的是通過網(wǎng)絡傳輸序列化的ILoggingEvent實例來記錄日志到遠程實體辫塌。當使用SocketAppender時,線路上的日志事件將以明文形式發(fā)送派哲。然而臼氨,當使用SSLSocketAppender時,日志事件是通過安全通道傳遞的芭届。

序列化事件的實際類型是LoggingEventVO储矩,它實現(xiàn)了ILoggingEvent接口。然而褂乍,就日志事件而言持隧,遠程日志記錄是非侵入性的。在反序列化后的接收端逃片,可以像在本地生成一樣記錄事件屡拨。運行在不同機器上的多個SocketAppender實例可以將它們的日志輸出定向到格式固定的中央日志服務器。SocketAppender不接受關聯(lián)的layout褥实,因為它將序列化的事件發(fā)送到遠程服務器呀狼。SocketAppender運行在傳輸控制協(xié)議(TCP)層之上,TCP層提供了一個可靠的性锭、有序的赠潦、流控制的端到端八位字節(jié)流。因此草冈,如果遠程服務器是可訪問的她奥,那么日志事件最終將到達那里瓮增。如果遠程服務器關閉或無法訪問,日志事件將被刪除哩俭。當服務器恢復時绷跑,事件傳輸將透明地恢復。這種透明的重連接由一個連接器線程執(zhí)行凡资,該線程定期嘗試連接到服務器砸捏。

日志事件由本機TCP實現(xiàn)自動緩沖。這意味著隙赁,如果到服務器的鏈接很慢垦藏,但是仍然比客戶機生成事件的速度快,客戶機將不會受到慢速網(wǎng)絡連接的影響伞访。但是掂骏,如果網(wǎng)絡連接比事件生成的速度慢,那么客戶機只能以網(wǎng)絡速度前進厚掷。特別是在連接到服務器的網(wǎng)絡連接關閉的極端情況下弟灼,客戶機最終將被阻塞∶昂冢或者田绑,如果網(wǎng)絡鏈接已打開,但服務器已關閉抡爹,則不會阻塞客戶機掩驱,盡管日志事件將由于服務器不可用而丟失。

即使SocketAppender不再附加到任何日志程序豁延,它也不會在連接器線程存在時被垃圾回收昙篙。連接器線程僅在與服務器的連接關閉時才存在。為了避免這種垃圾收集問題诱咏,您應該顯式地關閉SocketAppender。長生命周期應用程序會創(chuàng)建/銷毀許多SocketAppender實例缴挖,應該注意這個垃圾收集問題袋狞。大多數(shù)其他應用程序可以安全地忽略它。如果托管SocketAppenderJVMSocketAppender關閉之前(顯式關閉或垃圾收集之后關閉)退出映屋,那么管道中可能會丟失未傳輸?shù)臄?shù)據(jù)链蕊。這是基于Windows系統(tǒng)的常見問題放典。為了避免丟失數(shù)據(jù),通常可以顯式地關閉SocketAppender()沪饺,或者在退出應用程序之前調(diào)用LoggerContextstop()方法。

遠程服務器由remoteHostport屬性標識江醇。下表列出了SocketAppender屬性。SSLSocketAppender支持許多額外的配置屬性默责,這些屬性將在“使用SSL”一節(jié)中詳細介紹。

屬性名稱 類型 描述
includeCallerData boolean includeCallerData選項接受一個布爾值咸包。如果為true桃序,則調(diào)用方數(shù)據(jù)將對遠程主機可用。默認情況下烂瘫,不會向服務器發(fā)送調(diào)用方數(shù)據(jù)媒熊。
port int 遠程服務器的端口號。
reconnectionDelay Duration reconnectionDelay選項接受一個持續(xù)時間字符串坟比,比如“10秒”芦鳍,表示每次嘗試連接到服務器失敗之間的等待時間。這個選項的默認值是30秒葛账。將此選項設置為0將關閉重連接功能柠衅。注意,在成功連接到服務器的情況下注竿,將不存在連接器線程茄茁。
queueSize int queueSize屬性接受一個整數(shù)(大于零),該整數(shù)表示要保留的日志事件數(shù)量巩割,以便交付給遠程接收器裙顽。當隊列大小為1時,發(fā)送到遠程接收器的事件是同步的宣谈。當隊列大小大于1時愈犹,假設隊列中有可用空間,就會將新事件加入隊列闻丑。使用大于1的隊列長度可以通過消除由臨時網(wǎng)絡延遲引起的阻塞從而提高性能漩怎。還可參考eventDelayLimit屬性。
eventDelayLimit Duration eventDelayLimit選項接受一個持續(xù)時間字符串嗦嗡,比如“10秒”勋锤。它表示在本地隊列已滿(即已經(jīng)包含queueSize事件)時,在刪除事件之前等待的時間侥祭。如果遠程主機持續(xù)緩慢地接受事件叁执,可能會發(fā)生這種情況。此選項的默認值為100毫秒矮冬。
remoteHost String 服務器的主機名谈宛。
ssl SSLConfiguration 僅支持SSLSocketAppender,此屬性表示appender將使用SSL配置胎署,如“使用SSL”中所述吆录。

日志服務器選項

標準的Logback-Classic為服務器提供了兩個選項,用于接收來自SocketAppenderSSLSocketAppender的日志事件琼牧。

  • ServerSocketReceiver及其支持SSL-enabled程序的SSLServerSocketReceiver是接收器組件恢筝,可以在應用程序的logback.xml配置文件中配置這些組件哀卫,以便從遠程套接字追加器接收事件。有關配置細節(jié)和使用示例滋恬,請參見接收器Receivers的介紹聊训。
  • SimpleSocketServer及其支持SSL-enabled程序的SimpleSSLSocketServer都提供了易于使用的獨立Java應用程序,該應用程序的設計目的是配置并從shell的命令行接口運行恢氯。這些應用程序只是等待來自SocketAppenderSSLSocketAppender客戶機的日志事件带斑。每個接收到的事件都根據(jù)本地服務器策略進行日志記錄。下面給出了使用示例勋拟。

使用 SimpleSocketServer

SimpleSocketServer應用程序接受兩個命令行參數(shù):portconfigFile勋磕;其中port是要監(jiān)聽的端口,configFile是XML格式的配置腳本敢靡。

假設您在logback-examples/目錄中挂滓,使用以下命令啟動SimpleSocketServer

java ch.qos.logback.classic.net.SimpleSocketServer 6000 \
  src/main/java/chapters/appenders/socket/server1.xml

這里6000是要監(jiān)聽的端口號,server1.xml是一個配置腳本啸胧,它向根日志記錄器添加了一個ConsoleAppender和一個RollingFileAppender赶站。啟動SimpleSocketServer之后,您可以使用SocketAppender從多個客戶機向它發(fā)送日志事件纺念。與本手冊相關的例子包括兩個這樣的客戶端:chapters.appenders.SocketClient1chapters.appenders.SocketClient2兩個客戶機都在等待用戶在控制臺上輸入一行文本贝椿。文本被封裝在一個debug級別的日志事件中,然后發(fā)送到遠程服務器陷谱。這兩個客戶機在SocketAppender的配置上有所不同烙博。SocketClient1以編程方式配置追加器,而SocketClient2需要配置文件烟逊。

假設SimpleSocketServer在本地主機上運行渣窜,您可以使用以下命令連接到它:

java chapters.appenders.socket.SocketClient1 localhost 6000

您鍵入的每一行都應該出現(xiàn)在上一步中啟動的SimpleSocketServer的控制臺。如果停止并重啟SimpleSocketServer宪躯,客戶機將透明地重新連接到新服務器實例乔宿,盡管斷開連接時生成的事件將簡單地(并且不可挽回地)丟失。

SocketClient1不同访雪,示例應用程序SocketClient2本身并不配置logback予颤。它需要XML格式的配置文件。如下所示的配置文件client1.xml創(chuàng)建了一個SocketAppender并將其附加到根日志記錄器冬阳。

<configuration>
          
  <appender name="SOCKET" class="ch.qos.logback.classic.net.SocketAppender">
    <remoteHost>${host}</remoteHost>
    <port>${port}</port>
    <reconnectionDelay>10000</reconnectionDelay>
    <includeCallerData>${includeCallerData}</includeCallerData>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="SOCKET" />
  </root>  

</configuration>

注意,在上面的配置腳本中党饮,remoteHost肝陪、portincludeCallerData 屬性的值不是直接給出的,而是作為替代變量鍵給出的刑顺。變量的值可以指定為系統(tǒng)屬性:

java -Dhost=localhost -Dport=6000 -DincludeCallerData=false \
  chapters.appenders.socket.SocketClient2 src/main/java/chapters/appenders/socket/client1.xml

該命令的結果應該與前面的SocketClient1示例類似氯窍。

請允許我們重復一遍饲常,以強調(diào)日志事件的序列化不具有侵入性。反序列化事件與任何其他日志事件攜帶相同的信息狼讨。它可以像在本地生成一樣進行操作贝淤;除了默認情況下序列化日志事件不包含調(diào)用方數(shù)據(jù)之外。這里有一個例子來說明這一點政供。首先播聪,使用以下命令啟動SimpleSocketServer

 java ch.qos.logback.classic.net.SimpleSocketServer 6000 \
  src/main/java/chapters/appenders/socket/server2.xml

配置文件server2.xml創(chuàng)建一個ConsoleAppender,其布局輸出調(diào)用者的文件名和行號以及其他信息布隔。如果像以前一樣使用配置文件client1.xml運行SocketClient2离陶,你會注意到服務器端的輸出將包含兩個問號之間的括號,而不是文件名和行號的調(diào)用者:

2006-11-06 17:37:30,968 DEBUG [Thread-0] [?:?] chapters.appenders.socket.SocketClient2 - Hi

通過將includeCallerData選項設置為true衅檀,指示SocketAppender包含調(diào)用方數(shù)據(jù)招刨,可以很容易地更改結果。使用下面的命令就可以了:

java -Dhost=localhost -Dport=6000 -DincludeCallerData=true \
  chapters.appenders.socket.SocketClient2 src/main/java/chapters/appenders/socket/client1.xml

由于反序列化事件可以與本地生成的事件以相同的方式處理哀军,甚至可以將它們發(fā)送到另一臺服務器進行進一步處理沉眶。作為練習,您可能希望設置兩個服務器杉适,其中第一個服務器將其接收到的事件從客戶機傳輸?shù)降诙€服務器谎倔。

使用 SimpleSSLSocketServer

SimpleSSLSocketServerSimpleSocketServer一樣,也需要portconfigFile命令行參數(shù)淘衙。此外传藏,必須使用命令行中指定的系統(tǒng)屬性為日志服務器的X.509憑證提供位置和密碼。

假設您在logback-examples/目錄中彤守,使用以下命令啟動SimpleSSLSocketServer

java -Djavax.net.ssl.keyStore=src/main/java/chapters/appenders/socket/ssl/keystore.jks \
    -Djavax.net.ssl.keyStorePassword=changeit \
    ch.qos.logback.classic.net.SimpleSSLSocketServer 6000 \
    src/main/java/chapters/appenders/socket/ssl/server.xml

本例使用只適合于測試和實驗的X.509憑據(jù)運行SimpleSSLSocketServer毯侦。在生產(chǎn)設置中使用SimpleSSLSocketServer之前,您應該獲得一個適當?shù)?code>X.509憑據(jù)來標識您的日志服務器具垫。有關詳細信息侈离,請參見"使用SSL"。

因為服務器配置在根元素上指定debug="true"筝蚕,您將在服務器的啟動日志中看到將要使用的SSL配置卦碾。這對于驗證本地安全策略實現(xiàn)是否正確非常有用。

運行SimpleSSLSocketServer后起宽,可以使用SSLSocketAppender連接到服務器洲胖。下面的示例顯示了所需的appender配置:

<configuration debug="true">
          
  <appender name="SOCKET" class="ch.qos.logback.classic.net.SSLSocketAppender">
    <remoteHost>${host}</remoteHost>
    <port>${port}</port>
    <reconnectionDelay>10000</reconnectionDelay>
    <ssl>
      <trustStore>
        <location>${truststore}</location>
        <password>${password}</password>
      </trustStore>
    </ssl>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="SOCKET" />
  </root>  

</configuration>

注意,與前面的示例一樣坯沪,remoteHost绿映、port的值是使用替換的變量鍵指定的。此外,請注意ssl屬性及其嵌套的trustStore屬性的存在叉弦,該屬性指定存儲的位置和密碼丐一。這個配置是必要的,因為我們的示例服務器使用的是自簽名證書淹冰。有關SSLSocketAppenderSSL配置屬性的更多信息库车,請參見“使用SSL”。

通過在命令行上指定替換變量值作為系統(tǒng)屬性樱拴,我們可以使用這種配置運行客戶機應用程序:

java -Dhost=localhost -Dport=6000 \
    -Dtruststore=file:src/main/java/chapters/appenders/socket/ssl/truststore.jks \
    -Dpassword=changeit \
    chapters.appenders.socket.SocketClient2 src/main/java/chapters/appenders/socket/ssl/client.xml

與前面的示例一樣柠衍,您可以在客戶機應用程序提示時輸入一條消息,消息將被發(fā)送到日志服務器(現(xiàn)在通過一個安全通道)疹鳄,并顯示在控制臺拧略。

注意,命令行上給出的truststore屬性指定一個文件URL瘪弓,該URL標識可信任的存儲位置垫蛆。您還可以使用類路徑URL,如“使用SSL”中所述腺怯。

正如我們前面在服務器啟動時看到的袱饭,由于客戶機配置在根元素上指定了debug="true",客戶機的啟動日志記錄包括SSL配置的詳細信息呛占,以幫助審查本地策略的一致性虑乖。

ServerSocketAppender 和 SSLServerSocketAppender

前面討論的SocketAppender組件(及其支持ssl的對應組件)旨在允許應用程序通過網(wǎng)絡連接到遠程日志服務器,以便向服務器交付日志事件晾虑。

在某些情況下疹味,讓應用程序啟動到遠程日志服務器的連接可能不方便或不可行。對于這些情況帜篇,Logback提供ServerSocketAppender糙捺。

不啟動到遠程日志服務器的連接,ServerSocketAppender被動地監(jiān)聽TCP套接字笙隙,等待來自遠程客戶機的傳入連接洪灯。提交到附加器的日志事件分布到每個連接的客戶機。當沒有客戶機連接時發(fā)生的日志事件將被立即丟棄竟痰。

除了基本的ServerSocketAppender之外签钩,Logback還提供了SSLServerSocketAppender,它使用一個安全加密的通道將日志事件分發(fā)給每個連接的客戶機坏快。此外铅檩,啟用sslappender完全支持基于證書的相互認證,可以使用這種認證確保只有經(jīng)過授權的客戶端才能連接到appender來接收日志事件莽鸿。

為在線路上傳輸而編碼日志事件的方法與SocketAppender使用的方法相同柠并;每個事件都是ILoggingEvent的序列化實例。只有連接啟動的方向是相反的。SocketAppender在建立到日志服務器的連接時充當主動對等點臼予,而ServerSocketAppender是被動的;它偵聽來自客戶機的傳入連接啃沪。

ServerSocketAppender子類型僅用于Logback接收器組件粘拾。有關此組件類型的附加信息,請參見接收器创千。ServerSocketAppender支持以下配置屬性:

屬性名稱 類型 描述
address String 附加程序將偵聽的本地網(wǎng)絡接口地址缰雇。如果未指定此屬性,則追加器將偵聽所有網(wǎng)絡接口追驴。
includeCallerData boolean 如果為真械哟,則調(diào)用方數(shù)據(jù)將對遠程主機可用。默認情況下殿雪,不會向客戶機發(fā)送調(diào)用方數(shù)據(jù)暇咆。
port int 附加程序將偵聽的端口號。
ssl SSLConfiguration 僅支持SSLServerSocketAppender丙曙,此屬性提供了將由appender使用的SSL配置爸业,如“使用SSl”中所述。

下面的示例演示了一個使用ServerSocketAppender的配置:

<configuration debug="true">
  <appender name="SERVER" 
    class="ch.qos.logback.classic.net.server.ServerSocketAppender">
    <port>${port}</port>
    <includeCallerData>${includeCallerData}</includeCallerData>
  </appender>

  <root level="debug">
    <appender-ref ref="SERVER" />
  </root>  

</configuration>

注意亏镰,此配置與前面的示例不同扯旷,僅在為appender指定的類中使用ServerSocketAppender,并且在沒有remoteHost屬性的情況下——此appender被動地等待來自遠程主機的入站連接索抓,而不是打開到遠程日志服務器的連接钧忽。

下面的示例演示了使用SSLServerSocketAppender的配置。

<configuration debug="true">
  <appender name="SERVER" 
    class="ch.qos.logback.classic.net.server.SSLServerSocketAppender">
    <port>${port}</port>
    <includeCallerData>${includeCallerData}</includeCallerData>
    <ssl>
      <keyStore>
        <location>${keystore}</location>
        <password>${password}</password>
      </keyStore>
    </ssl>
  </appender>

  <root level="debug">
    <appender-ref ref="SERVER" />
  </root>  

</configuration>

此配置與前一個配置之間的主要區(qū)別在于逼肯,appenderclass屬性標識了SSLServerSocketAppender類型耸黑,以及嵌套ssl元素的存在,在本例中汉矿,嵌套ssl元素指定了包含附加器X.509憑據(jù)的密鑰存儲庫的配置崎坊。有關SSL配置屬性的信息,請參閱“使用SSL”洲拇。

因為ServerSocketAppender子類型被設計用于與接收器組件一起使用奈揍,所以我們將接收器的章節(jié)提供使用示例。

SMTPAppender

SMTPAppender將日志事件累積到一個或多個固定大小的緩沖區(qū)中赋续,并在發(fā)生用戶指定的事件后通過電子郵件發(fā)送適當緩沖區(qū)的內(nèi)容男翰。SMTP電子郵件傳輸(發(fā)送)是異步執(zhí)行的。默認情況下纽乱,電子郵件傳輸由級別錯誤的日志事件觸發(fā)蛾绎。此外,默認情況下,所有事件都使用一個緩沖區(qū)租冠。

下表總結了SMTPAppender的各種性能鹏倘。

屬性名稱 類型 描述
smtpHost String SMTP服務器的主機名。這個參數(shù)是強制性的顽爹。
smtpPort int SMTP服務器正在監(jiān)聽的端口纤泵。默認為25。
to String 收件人的電子郵件地址镜粤。會將觸發(fā)事件作為每個發(fā)出電子郵件的內(nèi)容捏题。可以通過用逗號分隔目標地址來指定多個收件人肉渴。另外公荧,還可以使用多個<to>元素指定多個收件人。
from String SMTPAppender以通常的電子郵件地址格式發(fā)送的電子郵件的發(fā)起者同规。如果您希望包含發(fā)送者的名稱循狰,則使用“Adam Smith <smith@moral.org>”格式,以便消息顯示為源自“Adam Smith <smith@moral.org>”
subject String 郵件的主題。它可以是PatternLayout作為有效轉換模式接受的任何值瘤睹。布局將在下一章討論。發(fā)出的電子郵件消息將具有與在觸發(fā)電子郵件消息的日志事件上應用模式相對應的主題行昧识。假設subject選項設置為“Log: %logger - %msg”,并且觸發(fā)事件的日志程序名為“com.foo.Bar”盗扒,并包含消息“Hello world”跪楞,然后發(fā)出的電子郵件將有主題行“Log: com.foo.Bar - Hello World”。默認情況下侣灶,該選項設置為“%logger{20} - %m”甸祭。
discriminator Discriminator discriminator的幫助下,SMTPAppender可以根據(jù)鑒別器返回的值將傳入的事件分散到不同的緩沖區(qū)中褥影。默認識別器總是返回相同的值池户,以便對所有事件使用相同的緩沖區(qū)。通過指定非默認識別器凡怎,可以接收包含與特定用戶校焦、用戶會話或客戶端IP地址相關的事件的電子郵件消息。
evaluator Ievaluator 該選項通過創(chuàng)建一個新的<EventEvaluator/>元素來聲明统倒。需要通過class屬性指定用戶希望用作SMTPAppender求值器的類的名稱寨典。在沒有此選項的情況下,SMTPAppender被分配一個OnErrorEvaluator實例房匆,該實例在遇到ERROR級別或更高級別的事件時觸發(fā)電子郵件傳輸耸成。Logback附帶了其他幾個評估器报亩,即OnMarkerEvaluator(下面討論)和一個名為JaninoEventEvaluator的強大評估器,將在另一章討論井氢。最新版本的logback附帶了一個更強大的評估器GEventEvaluator弦追。
cyclicBufferTracker CyclicBufferTracker 顧名思義,CyclicBufferTracker類的一個實例跟蹤循環(huán)緩沖區(qū)毙沾。它是基于識別器返回的鍵來實現(xiàn)的(見上面)骗卜。如果您沒有指定一個cyclicBufferTracker,那么將自動創(chuàng)建一個CyclicBufferTracker實例左胞。默認情況下,該實例將事件保存在大小為256的循環(huán)緩沖區(qū)中举户。您可以在bufferSize選項的幫助下更改大小(參見下面)烤宙。
username String 在普通用戶/密碼身份驗證期間使用的用戶名值。默認情況下俭嘁,該參數(shù)為null躺枕。
password String 用于普通用戶/密碼身份驗證的密碼值。默認情況下供填,該參數(shù)為null拐云。
STARTTLS boolean 如果將該參數(shù)設置為true,則此附加器將發(fā)出STARTTLS命令(如果服務器支持該命令)近她,導致連接切換到SSL叉瘩。注意,連接最初是不加密的粘捎。默認情況下薇缅,該參數(shù)設置為false
SSL boolean 如果將此參數(shù)設置為true攒磨,則此追加器將打開到服務器的SSL連接泳桦。默認情況下,該參數(shù)設置為false娩缰。
charsetEncoding String 發(fā)出的電子郵件將被編碼在指定的字符集中灸撰。默認的字符集編碼是“UTF-8”,這在大多數(shù)情況下都能很好地工作拼坎。
localhost String 如果SMTP客戶機的主機名沒有正確配置浮毯,例如,如果客戶機主機名沒有完全限定演痒,某些SMTP服務器可能會拒絕客戶機發(fā)送的HELO/EHLO命令亲轨。要克服這個問題,可以將localhost屬性的值設置為客戶機主機的完全限定名鸟顺。參見在com.sun.mail.smtp包中的“mail.smtp.localhost”屬性文檔惦蚊。
asynchronousSending boolean 此屬性確定電子郵件傳輸是否異步完成器虾。默認情況下,異步發(fā)送屬性為“true”蹦锋。然而兆沙,在某些情況下異步發(fā)送可能是不合適的。例如莉掂,如果應用程序使用SMTPAppender發(fā)送警報以響應致命錯誤葛圃,然后退出,相關線程可能沒有時間發(fā)送警報電子郵件憎妙。在本例中库正,將用于同步電子郵件傳輸?shù)漠惒桨l(fā)送屬性設置為“false”
includeCallerData boolean 默認情況下厘唾,includeCallerData被設置為false褥符。如果啟用了異步發(fā)送,并且希望在日志中包含調(diào)用方數(shù)據(jù)抚垃,則應該將includeCallerData設置為true喷楣。
sessionViaJNDI boolean SMTPAppender依賴于javax.mail.Session發(fā)送電子郵件消息。默認情況下鹤树,sessionViaJNDI被設置為false铣焊,因此javax.mail.Session實例由SMTPAppender本身使用用戶指定的屬性構建。如果將sessionViaJNDI屬性設置為true罕伯,則javax.mail.Session對象將通過JNDI檢索曲伊。還請參見jndiLocation屬性。通過JNDI檢索Session可以減少配置/重新配置相同信息所需的位置數(shù)量捣炬,從而使應用程序更加dryer熊昌。有關在Tomcat中配置資源的更多信息,請參見JNDI資源指南湿酸。如該文檔中所述婿屹,在從JNDI檢索Session時,請確保從web應用程序WEB-INF/lib文件夾中刪除mail.jaractivation.jar推溃。
jndiLocation String javax.mail.Session位于JNDI中的位置昂利。默認情況下,jndiLocation被設置為“java:comp/env/mail/Session”铁坎。

未完待續(xù)蜂奸。。硬萍。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末扩所,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子朴乖,更是在濱河造成了極大的恐慌祖屏,老刑警劉巖助赞,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異袁勺,居然都是意外死亡雹食,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門期丰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來群叶,“玉大人,你說我怎么就攤上這事钝荡〗至ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵埠通,是天一觀的道長几晤。 經(jīng)常有香客問我,道長植阴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任圾浅,我火速辦了婚禮掠手,結果婚禮上,老公的妹妹穿的比我還像新娘狸捕。我一直安慰自己喷鸽,他們只是感情好,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布灸拍。 她就那樣靜靜地躺著做祝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鸡岗。 梳的紋絲不亂的頭發(fā)上混槐,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音轩性,去河邊找鬼声登。 笑死,一個胖子當著我的面吹牛揣苏,可吹牛的內(nèi)容都是我干的悯嗓。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼卸察,長吁一口氣:“原來是場噩夢啊……” “哼脯厨!你這毒婦竟也來了?” 一聲冷哼從身側響起坑质,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤合武,失蹤者是張志新(化名)和其女友劉穎临梗,沒想到半個月后盏阶,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體绑谣,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年罩息,在試婚紗的時候發(fā)現(xiàn)自己被綠了岂贩。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片茫经。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖萎津,靈堂內(nèi)的尸體忽然破棺而出卸伞,到底是詐尸還是另有隱情,我是刑警寧澤锉屈,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布荤傲,位于F島的核電站,受9級特大地震影響颈渊,放射性物質發(fā)生泄漏遂黍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一俊嗽、第九天 我趴在偏房一處隱蔽的房頂上張望雾家。 院中可真熱鬧,春花似錦绍豁、人聲如沸芯咧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽敬飒。三九已至,卻和暖如春芬位,著一層夾襖步出監(jiān)牢的瞬間无拗,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工晶衷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蓝纲,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓晌纫,卻偏偏與公主長得像税迷,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子锹漱,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 作為Java開發(fā)人員箭养,對于日志記錄框架一定非常熟悉。而且?guī)缀踉谒袘美锩娓珉梗欢〞玫礁鞣N各樣的日志框架用來記錄程...
    意識流丶閱讀 13,927評論 0 13
  • 簡單日志配置 logback的介紹及配置 logback的使用 logback.xml配置示例 一.簡單日志配置 ...
    CoderZS閱讀 1,968評論 0 16
  • from:https://www.cnblogs.com/ITtangtang/p/3926665.html一毕泌、L...
    enshunyan閱讀 3,292評論 0 0
  • 在應用程序中添加日志記錄總的來說基于三個目的:監(jiān)視代碼中變量的變化情況喝检,周期性的記錄到文件中供其他應用進行統(tǒng)計分析...
    時待吾閱讀 4,988評論 0 6
  • 曼谷大皇宮——金碧輝煌的宮殿廟宇,鳥語花香的皇家庭院撼泛,嘆為觀止的壁畫挠说,以及涌動的人群和灼熱的陽光。 四面佛——聽說...
    熠一插畫閱讀 293評論 0 0