日志組件介紹
常用組件
- jul
- jcl
- log4j2
- log4j
- slf4j
- logback
- jboss-logging
發(fā)展歷史
- 1996年早期,歐洲安全電子市場項(xiàng)目組決定編寫它自己的程序跟蹤API(Tracing API)。經(jīng)過不斷的完善,這個(gè)API終于成為一個(gè)十分受歡迎的Java日志軟件包,即Log4j。后來Log4j成為Apache基金會項(xiàng)目中的一員。
- 期間Log4j近乎成了Java社區(qū)的日志標(biāo)準(zhǔn)。據(jù)說Apache基金會還曾經(jīng)建議Sun引入Log4j到j(luò)ava的標(biāo)準(zhǔn)庫中,但Sun拒絕了。
- 2002年Java1.4發(fā)布,Sun推出了自己的日志庫JUL(Java Util Logging),其實(shí)現(xiàn)基本模仿了Log4j的實(shí)現(xiàn)。在JUL出來以前,Log4j就已經(jīng)成為一項(xiàng)成熟的技術(shù),使得Log4j在選擇上占據(jù)了一定的優(yōu)勢。
- 接著,Apache推出了Jakarta Commons Logging,JCL只是定義了一套日志接口(其內(nèi)部也提供一個(gè)Simple Log的簡單實(shí)現(xiàn)),支持運(yùn)行時(shí)動(dòng)態(tài)加載日志組件的實(shí)現(xiàn),也就是說,在你應(yīng)用代碼里,只需調(diào)用Commons Logging的接口,底層實(shí)現(xiàn)可以是Log4j,也可以是Java Util Logging。
- 后來(2006年),Ceki Gülcü不適應(yīng)Apache的工作方式,離開了Apache。然后先后創(chuàng)建了Slf4j(日志門面接口,類似于Commons Logging)和Logback(Slf4j的實(shí)現(xiàn))兩個(gè)項(xiàng)目,并回瑞典創(chuàng)建了QOS公司,QOS官網(wǎng)上是這樣描述Logback的:The Generic,Reliable Fast&Flexible Logging Framework(一個(gè)通用,可靠,快速且靈活的日志框架)。
- 現(xiàn)今,Java日志領(lǐng)域被劃分為兩大陣營:Commons Logging陣營和Slf4j陣營。Commons Logging在Apache大樹的籠罩下,有很大的用戶基數(shù),早期spring的集成框架。但有證據(jù)表明,形式正在發(fā)生變化,spring boot 默認(rèn)使用了 Slf4j。
- Apache眼看有被Logback反超的勢頭,于2012-07重寫了Log4j 1.x,成立了新的項(xiàng)目Log4j 2, Log4j 2具有Logback的所有特性。
slf4j


Spring Boot默認(rèn)集成日志框架logback
簡介
Logger、appender及l(fā)ayout
Logger作為日志的記錄器,把它關(guān)聯(lián)到應(yīng)用的對應(yīng)的context上后,主要用于存放日志對象,也可以定義日志類型、級別。
Appender主要用于指定日志輸出的目的地,目的地可以是控制臺、文件、遠(yuǎn)程套接字服務(wù)器、 MySQL、 PostreSQL、 Oracle和其他數(shù)據(jù)庫、 JMS和遠(yuǎn)程UNIX Syslog守護(hù)進(jìn)程等。
Layout 負(fù)責(zé)把事件轉(zhuǎn)換成字符串,格式化的日志信息的輸出。
logger context
各個(gè)logger 都被關(guān)聯(lián)到一個(gè) LoggerContext,LoggerContext負(fù)責(zé)制造logger,也負(fù)責(zé)以樹結(jié)構(gòu)排列各 logger。其他所有l(wèi)ogger也通過org.slf4j.LoggerFactory 類的靜態(tài)方法getLogger取得。 getLogger方法以 logger 名稱為參數(shù)。用同一名字調(diào)用LoggerFactory.getLogger 方法所得到的永遠(yuǎn)都是同一個(gè)logger對象的引用。
有效級別及級別的繼承
Logger 可以被分配級別。級別包括:TRACE、DEBUG、INFO、WARN 和 ERROR,定義于 ch.qos.logback.classic.Level類。如果 logger沒有被分配級別,那么它將從有被分配級別的最近的祖先那里繼承級別。root logger 默認(rèn)級別是 DEBUG。
打印方法與基本的選擇規(guī)則
打印方法決定記錄請求的級別。例如,如果 L 是一個(gè) logger 實(shí)例,那么,語句 L.info("..")是一條級別為 INFO 的記錄語句。記錄請求的級別在高于或等于其 logger 的有效級別時(shí)被稱為被啟用,否則,稱為被禁用。記錄請求級別為 p,其logger的有效級別為 q,只有則當(dāng) p>=q時(shí),該請求才會被執(zhí)行。
該規(guī)則是 logback 的核心。級別排序?yàn)椋?TRACE < DEBUG < INFO < WARN < ERROR。
關(guān)于多環(huán)境
- 通過spring boot 的配置文件指定
logging:
config: classpath:conf/logback-dev.xml
- 通過logback-spring.xml文件,spring使用標(biāo)簽管理
<springProfile name="dev">
<logger name="com.sdcm.pmp" level="debug"/>
</springProfile>
logback配置信息
configuration
| 名稱 | 說明, |
|---|---|
| scan | 當(dāng)此屬性設(shè)置為true時(shí),配置文件如果發(fā)生改變,將會被重新加載,默認(rèn)值為true。 |
| scanPeriod | 設(shè)置監(jiān)測配置文件是否有修改的時(shí)間間隔,如果沒有給出時(shí)間單位,默認(rèn)單位是毫秒。當(dāng)scan為true時(shí),此屬性生效。默認(rèn)的時(shí)間間隔為1分鐘。 |
| debug | 當(dāng)此屬性設(shè)置為true時(shí),將打印出logback內(nèi)部日志信息,實(shí)時(shí)查看logback運(yùn)行狀態(tài)。默認(rèn)值為false。 |
contextName
每個(gè)logger都關(guān)聯(lián)到logger上下文,默認(rèn)上下文名稱為“default”。但可以使用contextName設(shè)置成其他名字,用于區(qū)分不同應(yīng)用程序的記錄。一旦設(shè)置,不能修改。
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>myAppName</contextName>
</configuration>
property
用來定義變量值的標(biāo)簽,property 有兩個(gè)屬性,name和value;其中name的值是變量的名稱,value的值時(shí)變量定義的值。通過property定義的值會被插入到logger上下文中。定義變量后,可以使“${}”來使用變量。
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<property name="APP_Name" value="myAppName" />
<contextName>${APP_Name}</contextName>
</configuration>
timestamp
兩個(gè)屬性 key:標(biāo)識此timestamp的名字;datePattern:設(shè)置將當(dāng)前時(shí)間(解析配置文件的時(shí)間)轉(zhuǎn)換為字符串的模式,遵循java.txt.SimpleDateFormat的格式。
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>
</configuration>
loger
用來設(shè)置某一個(gè)包或者具體的某一個(gè)類的日志打印級別、以及指定appender。loger僅有一個(gè)name屬性,一個(gè)可選的level和一個(gè)可選的addtivity屬性。
| 名稱 | 說明, |
|---|---|
| name | 用來指定受此loger約束的某一個(gè)包或者具體的某一個(gè)類。 |
| level | 用來設(shè)置打印級別,大小寫無關(guān):TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,還有一個(gè)特殊值INHERITED或者同義詞NULL,代表強(qiáng)制執(zhí)行上級的級別。如果未設(shè)置此屬性,那么當(dāng)前l(fā)oger將會繼承上級的級別。 |
| addtivity | 是否向上級loger傳遞打印信息。默認(rèn)是true。loger可以包含零個(gè)或多個(gè)appender-ref元素,標(biāo)識這個(gè)appender將會添加到這個(gè)loger。當(dāng)loger中包含appender-ref時(shí),如果addtivity=true,則會將打印信息傳遞到root;如果addtivity=false,則只會在loger中appender-ref打印信息,不會向上傳遞。 |
root
也是loger元素,但是它是根loger。只有一個(gè)level屬性,應(yīng)為已經(jīng)被命名為"root".
appender
appender是configuration的子節(jié)點(diǎn),是負(fù)責(zé)寫日志的組件。
appender有兩個(gè)必要屬性name和class。name指定appender名稱,class指定appender的全限定名。
ConsoleAppender
把日志添加到控制臺,有以下子節(jié)點(diǎn):
- encoder:對日志進(jìn)行格式化。
- target:字符串 System.out 或者 System.err ,默認(rèn) System.out。
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- Console 輸出設(shè)置 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | %thread | %-5level | %logger{64}:%line | %msg%n</pattern>
<charset>UTF8</charset>
</encoder>
</appender>
</configuration>
FileAppender
把日志添加到文件,有以下子節(jié)點(diǎn):
- file:被寫入的文件名,可以是相對目錄,也可以是絕對目錄,如果上級目錄不存在會自動(dòng)創(chuàng)建,沒有默認(rèn)值。
- append:如果是 true,日志被追加到文件結(jié)尾,如果是 false,清空現(xiàn)存文件,默認(rèn)是true。
- encoder:對記錄事件進(jìn)行格式化。
- prudent:如果是 true,日志會被安全的寫入文件,即使其他的FileAppender也在向此文件做寫入操作,效率低,默認(rèn)是 false。
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.FileAppender">
<file>${logPath}/${appName}-${appModule}-${appVersion}-${appNode}.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | %thread | %-5level | %logger{64}:%line | %msg%n</pattern>
</encoder>
</appender>
</configuration>
RollingFileAppender
滾動(dòng)記錄文件,先將日志記錄到指定文件,當(dāng)符合某個(gè)條件時(shí),將日志記錄到其他文件。有以下子節(jié)點(diǎn):
- file:被寫入的文件名,可以是相對目錄,也可以是絕對目錄,如果上級目錄不存在會自動(dòng)創(chuàng)建,沒有默認(rèn)值。
- append:如果是 true,日志被追加到文件結(jié)尾,如果是 false,清空現(xiàn)存文件,默認(rèn)是true。
- encoder:對記錄事件進(jìn)行格式化。
- rollingPolicy:當(dāng)發(fā)生滾動(dòng)時(shí),決定 RollingFileAppender 的行為,涉及文件移動(dòng)和重命名。
- triggeringPolicy:告知 RollingFileAppender 何時(shí)激活滾動(dòng)。
- prudent:當(dāng)為true時(shí),不支持FixedWindowRollingPolicy。支持TimeBasedRollingPolicy,但是有兩個(gè)限制,1不支持也不允許文件壓縮,2不能設(shè)置file屬性,必須留空。
TimeBasedRollingPolicy
最常用的滾動(dòng)策略,它根據(jù)時(shí)間來制定滾動(dòng)策略,既負(fù)責(zé)滾動(dòng)也負(fù)責(zé)出發(fā)滾動(dòng)。有以下子節(jié)點(diǎn):
- fileNamePattern:必要節(jié)點(diǎn),包含文件名及“%d”轉(zhuǎn)換符, “%d”可以包含一個(gè)java.text.SimpleDateFormat指定的時(shí)間格式,如:%d{yyyy-MM}。如果直接使用 %d,默認(rèn)格式是 yyyy-MM-dd。RollingFileAppender 的file字節(jié)點(diǎn)可有可無,通過設(shè)置file,可以為活動(dòng)文件和歸檔文件指定不同位置,當(dāng)前日志總是記錄到file指定的文件(活動(dòng)文件),活動(dòng)文件的名字不會改變;如果沒設(shè)置file,活動(dòng)文件的名字會根據(jù)fileNamePattern 的值,每隔一段時(shí)間改變一次?!?”或者“\”會被當(dāng)做目錄分隔符。
- maxHistory:可選節(jié)點(diǎn),控制保留的歸檔文件的最大數(shù)量,超出數(shù)量就刪除舊文件。假設(shè)設(shè)置每個(gè)月滾動(dòng),且maxHistory是6,則只保存最近6個(gè)月的文件,刪除之前的舊文件。注意,刪除舊文件是,那些為了歸檔而創(chuàng)建的目錄也會被刪除。
FixedWindowRollingPolicy
根據(jù)固定窗口算法重命名文件的滾動(dòng)策略。有以下子節(jié)點(diǎn):
- minIndex:窗口索引最小值
- maxIndex:窗口索引最大值,當(dāng)用戶指定的窗口過大時(shí),會自動(dòng)將窗口設(shè)置為12。
- fileNamePattern:必須包含“%i”例如,假設(shè)最小值和最大值分別為1和2,命名模式為 mylog%i.log,會產(chǎn)生歸檔文件mylog1.log和mylog2.log。還可以指定文件壓縮選項(xiàng),例如,mylog%i.log.gz 或者 沒有l(wèi)og%i.log.zip
SizeBasedTriggeringPolicy
查看當(dāng)前活動(dòng)文件的大小,如果超過指定大小會告知RollingFileAppender 觸發(fā)當(dāng)前活動(dòng)文件滾動(dòng)。只有一個(gè)節(jié)點(diǎn):
- maxFileSize:這是活動(dòng)文件的大小,默認(rèn)值是10MB。
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/${appName}-${appModule}-${appVersion}-${appNode}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件輸出的文件名-->
<FileNamePattern>${logPath}/${appName}-${appModule}-${appVersion}-${appNode}.%d{yyyy-MM-dd}.%i.log.gz</FileNamePattern>
<!--日志文件保留天數(shù)-->
<MaxHistory>180</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${appName}-${appModule}-${appVersion}-${appNode} | %d{yyyy-MM-dd HH:mm:ss.SSS} | %thread | %-5level | %logger{64}:%line | %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>128MB</MaxFileSize>
</triggeringPolicy>
</appender>
</configuration
SocketAppender && SSLSocketAppender
SocketAppender就是被設(shè)計(jì)用來輸出日志到遠(yuǎn)程實(shí)例中的。 SocketAppender輸出日志采用明文方式, SSLSocketAppender則采用加密方式傳輸日志。
- includeCallerData:是否包含調(diào)用者的信息如果為true,則以下日志輸出的 ?:? 會替換成調(diào)用者的文件名跟行號,為false,則為問號。
- port:端口號。
- reconnectionDelay:重連延時(shí),如果設(shè)置成“10 seconds”,就會在連接u武器失敗后,等待10秒,再連接。默認(rèn)值:“30 seconds”。如果設(shè)置成0,則關(guān)閉重連功能。
- queueSize:設(shè)置緩沖日志數(shù),如果設(shè)置成0,日志發(fā)送是同步的,如果設(shè)置成大于0的值,會將日志放入隊(duì)列,隊(duì)列長度到達(dá)指定值,在統(tǒng)一發(fā)送??梢约哟蠓?wù)吞吐量。
- eventDelayLimit:設(shè)置日志超時(shí)丟棄時(shí)間。當(dāng)設(shè)置“10 seconds”類似的值,如果日志隊(duì)列已滿,而服務(wù)器長時(shí)間來不及接收,當(dāng)滯留時(shí)間超過10 seconds,日志就會被丟棄。默認(rèn)值:100 milliseconds
- remoteHost:遠(yuǎn)程日志服務(wù)器的IP
- ssl:只在SSLSocketAppender包含該屬性節(jié)點(diǎn)。提供SSL配置。
SMTPAppender
可以將logging event存放在一個(gè)或多個(gè)固定大小的緩沖區(qū)中,然后在用戶指定的event到來之時(shí),將適當(dāng)?shù)拇笮〉膌ogging event以郵件方式發(fā)送給運(yùn)維人員 。
- smtpHost:SMTP server的地址,必需指定。如網(wǎng)易的SMTP服務(wù)器地址是: smtp.163.com。
- smtpPort:SMTP server的端口地址。默認(rèn)值:25。
- to:指定發(fā)送到那個(gè)郵箱,可設(shè)置多個(gè)to屬性,指定多個(gè)目的郵箱。
- from:指定發(fā)件人名稱。如果設(shè)置成“Adam Smith <smith@moral.org> ”,則郵件發(fā)件人將會是“Adam Smith smith@moral.org ”
- subject:指定emial的標(biāo)題,它需要滿足PatternLayout中的格式要求。如果設(shè)置成“ Log: %logger - %msg”,就案例來講,則發(fā)送郵件時(shí),標(biāo)題為“ Log: com.foo.Bar - Hello World ”。默認(rèn)值: "%logger{20} - %m".
- discriminator:通過Discriminator, SMTPAppender可以根據(jù)Discriminator的返回值,將到來的logging event分發(fā)到不同的緩沖區(qū)中。默認(rèn)情況下,總是返回相同的值來達(dá)到使用一個(gè)緩沖區(qū)的目的。
- evaluator:指定觸發(fā)日志發(fā)送的條件。通過<evaluator class=... />指定EventEvaluator接口的實(shí)現(xiàn)類。默認(rèn)情況下SMTPAppeender使用的是OnErrorEvaluator,表示當(dāng)發(fā)送ERROR或更高級別的日志請求時(shí),發(fā)送郵件。Logback提供了幾個(gè)evaluators:
- OnErrorEvaluator
- OnMarkerEvaluator
- JaninoEventEvaluator
- GEventEvaluator
- cyclicBufferTracker:指定一個(gè)cyclicBufferTracker跟蹤cyclic buffer。它是基于discriminator的實(shí)現(xiàn)的。如果你不指定,默認(rèn)會創(chuàng)建一個(gè)CyclicBufferTracker ,默認(rèn)設(shè)置cyclic buffer大小為256。你也可以手動(dòng)指定使用默認(rèn)的CyclicBufferTracker,并且通過bufferSize屬性修改默認(rèn)的緩沖區(qū)接收多少條logging event。
- username:發(fā)送郵件賬號,默認(rèn)為null。
- password:發(fā)送郵件密碼,默認(rèn)為null。
- STARTTLS:如果設(shè)置為true,appender會嘗試使用STARTTLS命令,如果服務(wù)端支持,則會將明文連接轉(zhuǎn)換成加密連接。需要注意的是,與日志服務(wù)器連接一開始是未加密的。默認(rèn)值:false。
- SSL:如果設(shè)置為true,appender將會使用SSL連接到日志服務(wù)器。默認(rèn)值:false。
- charsetEncoding:指定郵件信息的編碼格式。默認(rèn)值:UTF-8。
- localhost:如果smtpHost沒有正確配置,比如說不是完整的地址。這時(shí)候就需要localhost這個(gè)屬性提供服務(wù)器的完整路徑(如同java中的完全限定名 ),詳情參考com.sun.mail.smtp 中的mail.smtp.localhost屬性
- asynchronousSending:這個(gè)屬性決定email的發(fā)送是否是異步。默認(rèn):true,異步發(fā)送但是在某些情況下,需要以同步方式發(fā)送錯(cuò)誤日志的郵件給管理人員,防止不能及時(shí)維護(hù)應(yīng)用。
- includeCallerData:指定是否包含callerData在日志中。默認(rèn):false。
- sessionViaJNDI:SMTPAppender依賴javax.mail.Session來發(fā)送郵件。默認(rèn)情況下,sessionViaJNDI為false。javax.mail.Session實(shí)例的創(chuàng)建依賴于SMTPAppender本身的配置信息。如果設(shè)置為true,則Session的創(chuàng)建時(shí)通過JNDI獲取引用。這樣做的好處可以讓你的代碼復(fù)用更好,讓配置更簡潔。需要注意的是,如果使用JNDI獲取Session對象,需要保證移除mail.jar以及activation.jar這兩個(gè)jar包。
- jndiLocation:如果sessionViaJNDI設(shè)置為true,則jndiLocation指定JNDI的資源名,默認(rèn)值為:"java:comp/env/mail/Session"。
DBAppender
可以將日志事件插入到3張數(shù)據(jù)表中。它們分別是logging_event,logging_event_property,logging_event_exception。這三張數(shù)據(jù)表必須在DBAppender工作之前存在。它們的sql腳本可以在 logback-classic/src/main/java/ch/qos/logback/classic/db/script folder 這個(gè)目錄下找到。這個(gè)腳本對大部分SQL數(shù)據(jù)庫都是有效的,除了少部分,少數(shù)語法有差異需要調(diào)整。
- connectionSource:數(shù)據(jù)庫連接信息。
SiftingAppender
提供過濾篩選日志的功能。你可以通過用戶的sessions的數(shù)據(jù)來篩選日志,然后分發(fā)到不同日志文件。
自定義Appender
你可以很簡單的創(chuàng)建自己的Appender,通過繼承父類AppenderBase。AppenderBase已經(jīng)實(shí)現(xiàn)了對filters,status以及一些其他被大多數(shù)appender共享的功能的支持。我們所要做的僅僅是實(shí)現(xiàn)append(Object evenObject)這個(gè)方法。
encoder && layout
區(qū)別
在0.9.19版本之前,都是使用layout來控制輸出的格式。在0.9.19就變成了使用encoder來控制。
encoder:主要工作有兩個(gè):①將一個(gè)event事件轉(zhuǎn)換成一組byte數(shù)組,②將轉(zhuǎn)換后的字節(jié)數(shù)據(jù)輸出到文件中。
layout:主要的功能就是:將一個(gè)event事件轉(zhuǎn)化為一個(gè)String字符串。
格式控制
| 轉(zhuǎn)換符 | 作用 |
|---|---|
| c {length}、lo {length}、logger {length} | 輸出日志的logger名,可有一個(gè)整形參數(shù),功能是縮短logger名,設(shè)置為0表示只輸入logger最右邊點(diǎn)符號之后的字符串。 Conversion specifier Logger name Result |
| C {length}、class {length} | 輸出執(zhí)行記錄請求的調(diào)用者的全限定名。參數(shù)與上面的一樣。盡量避免使用,除非執(zhí)行速度不造成任何問題。 |
| contextName、cn | 輸出上下文名稱。 |
| d{pattern}、date{pattern} | 輸出日志的打印日志,模式語法與java.text.SimpleDateFormat 兼容。 Conversion Pattern Result |
| F、file | 輸出執(zhí)行記錄請求的java源文件名。盡量避免使用,除非執(zhí)行速度不造成任何問題。 |
| caller{depth}、caller{depth, evaluator-1, ... evaluator-n} | 輸出生成日志的調(diào)用者的位置信息,整數(shù)選項(xiàng)表示輸出信息深度。 |
| L、line | 輸出執(zhí)行日志請求的行號。盡量避免使用,除非執(zhí)行速度不造成任何問題。 |
| m、msg、message | 輸出應(yīng)用程序提供的信息。 |
| M、method | 輸出執(zhí)行日志請求的方法名。盡量避免使用,除非執(zhí)行速度不造成任何問題。 |
| n | 輸出平臺先關(guān)的分行符“\n”或者“\r\n”。 |
| p、le、level | 輸出日志級別。 |
| r、relative | 輸出從程序啟動(dòng)到創(chuàng)建日志記錄的時(shí)間,單位是毫秒。 |
| t、thread | 輸出產(chǎn)生日志的線程名。 |
| replace(p){r,t} | p 為日志內(nèi)容,r 是正則表達(dá)式,將p 中符合r 的內(nèi)容替換為t。例如, "%replace(%msg){'\s', ''}"。 |
filter
Logback的過濾器基于三值邏輯(ternary logic),允許把它們組裝或成鏈,從而組成任意的復(fù)合過濾策略。過濾器很大程度上受到Linux的iptables啟發(fā)。這里的所謂三值邏輯是說,過濾器的返回值只能是ACCEPT、DENY和NEUTRAL的其中一個(gè)。
- 如果返回DENY,那么記錄事件立即被拋棄,不再經(jīng)過剩余過濾器;
- 如果返回NEUTRAL,那么有序列表里的下一個(gè)過濾器會接著處理記錄事件;
- 如果返回ACCEPT,那么記錄事件被立即處理,不再經(jīng)過剩余過濾器。
過濾器被添加到Appender中,為Appender添加一個(gè)或多個(gè)過濾器后,可以用任意條件對日志進(jìn)行過濾。Appender有多個(gè)過濾器時(shí),按照配置順序執(zhí)行。
LevelFilter
級別過濾器,根據(jù)日志級別進(jìn)行過濾。如果日志級別等于配置級別,過濾器會根據(jù)onMath 和 onMismatch接收或拒絕日志。有以下子節(jié)點(diǎn):
- level:設(shè)置過濾級別。
- onMatch:用于配置符合過濾條件的操作。
- onMismatch:用于配置不符合過濾條件的操作
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>
%-4relative [%thread] %-5level %logger{30} - %msg%n
</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
ThresholdFilter
當(dāng)日志級別等于或高于臨界值時(shí),過濾器返回NEUTRAL;當(dāng)日志級別低于臨界值時(shí),日志會被拒絕。
<configuration>
<appender name="CONSOLE"
class="ch.qos.logback.core.ConsoleAppender">
<!-- 過濾掉 TRACE 和 DEBUG 級別的日志-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<pattern>
%-4relative [%thread] %-5level %logger{30} - %msg%n
</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
EvaluatorFilter
求值過濾器,評估、鑒別日志是否符合指定條件。需要額外的兩個(gè)JAR包,commons-compiler.jar和janino.jar。
- evaluator:鑒別器,常用的鑒別器是JaninoEventEvaluato,也是默認(rèn)的鑒別器,它以任意的java布爾值表達(dá)式作為求值條件,求值條件在配置文件解釋過成功被動(dòng)態(tài)編譯,布爾值表達(dá)式返回true就表示符合過濾條件。evaluator有個(gè)子標(biāo)簽expression,用于配置求值條件。
- onMatch:用于配置符合過濾條件的操作。
- onMismatch:用于配置不符合過濾條件的操作
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator> <!-- 默認(rèn)為 ch.qos.logback.classic.boolex.JaninoEventEvaluator -->
<expression>return message.contains("billing");</expression>
</evaluator>
<OnMatch>ACCEPT </OnMatch>
<OnMismatch>DENY</OnMismatch>
</filter>
<encoder>
<pattern>
%-4relative [%thread] %-5level %logger - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Spring Boot下的日志歸集
思路
- 需要有個(gè)日志的服務(wù)器,用于歸集各個(gè)模塊產(chǎn)生的日志信息
- 每個(gè)模塊的日志除了輸出到本地,還要同步輸出到日志服務(wù)器
- 每個(gè)模塊輸出的日志格式應(yīng)該是統(tǒng)一的
- 日志服務(wù)器至少要提供精確、準(zhǔn)確的檢索能力
最簡方案:SocketAppender+ServerSocketReceiver
client端
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 彩色日志依賴的渲染類 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- 系統(tǒng)名稱 通過啟動(dòng)參數(shù) -Dapp.api.name="***" 指定 -->
<property scope="context" name="appName" value="${app.api.name:-appName}"/>
<!-- 模塊名稱 通過啟動(dòng)參數(shù) -Dapp.api.module="***" 指定 -->
<property scope="context" name="appModule" value="${app.api.module:-moduleName}"/>
<!-- 版本 通過啟動(dòng)參數(shù) -Dapp.api.version="***" 指定 -->
<property scope="context" name="appVersion" value="${app.api.version:-v1}"/>
<!-- 節(jié)點(diǎn)名稱 通過啟動(dòng)參數(shù) -Dapp.api.node="***" 指定 -->
<property scope="context" name="appNode" value="${app.api.node:-node1}"/>
<!-- 日志文件路徑 通過啟動(dòng)參數(shù) -Dapp.log.path="***" 指定 -->
<property scope="context" name="logPath" value="${app.log.path:-/joinway}"/>
<!-- 日志文件備份路徑 通過啟動(dòng)參數(shù) -Dapp.log.path="***" 指定 -->
<property scope="context" name="backPath" value="${logPath}/backFiles"/>
<property name="appName" value="${appName}-${appModule}-${appVersion}-${appNode}" />
<contextName>${appName}</contextName>
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN"
value="%clr(%cn){blue} | %clr(%date{yyyy-MM-dd HH:mm:ss.SSS}){yellow} | %clr(%-5level){highlight} | %clr(%thread){faint} | %clr(%logger{64}:%line){magenta} | %clr(%msg%n){cyan}${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<!-- Console 輸出設(shè)置 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>UTF8</charset>
</encoder>
</appender>
<appender name="SOCKET" class="ch.qos.logback.classic.net.SocketAppender">
<remoteHost>192.168.3.166</remoteHost>
<port>9898</port>
<reconnectionDelay>10000</reconnectionDelay>
<includeCallerData>true</includeCallerData>
</appender>
<logger name="org.springframework" level="INFO"/>
<logger name="DemoContorller2" level="TRACE" addtivity="false">
<appender-ref ref="SOCKET"/>
</logger>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
</root>
</configuration>
server端
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 彩色日志依賴的渲染類 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- 系統(tǒng)名稱 通過啟動(dòng)參數(shù) -Dapp.api.name="***" 指定 -->
<property scope="context" name="appName" value="${app.api.name:-appName}"/>
<!-- 模塊名稱 通過啟動(dòng)參數(shù) -Dapp.api.module="***" 指定 -->
<property scope="context" name="appModule" value="${app.api.module:-moduleName}"/>
<!-- 版本 通過啟動(dòng)參數(shù) -Dapp.api.version="***" 指定 -->
<property scope="context" name="appVersion" value="${app.api.version:-v1}"/>
<!-- 節(jié)點(diǎn)名稱 通過啟動(dòng)參數(shù) -Dapp.api.node="***" 指定 -->
<property scope="context" name="appNode" value="${app.api.node:-node1}"/>
<!-- 日志文件路徑 通過啟動(dòng)參數(shù) -Dapp.log.path="***" 指定 -->
<property scope="context" name="logPath" value="${app.log.path:-/joinway}"/>
<!-- 日志文件備份路徑 通過啟動(dòng)參數(shù) -Dapp.log.path="***" 指定 -->
<property scope="context" name="backPath" value="${logPath}/backFiles"/>
<property name="appName" value="${appName}-${appModule}-${appVersion}-${appNode}" />
<contextName>${appName}</contextName>
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN"
value="%clr(%cn){blue} | %clr(%date{yyyy-MM-dd HH:mm:ss.SSS}){yellow} | %clr(%-5level){highlight} | %clr(%thread){faint} | %clr(%logger{64}:%line){magenta} | %clr(%msg%n){cyan}${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<!-- Console 輸出設(shè)置 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>UTF8</charset>
</encoder>
</appender>
<logger name="org.springframework" level="INFO"/>
<logger name="DemoContorller2" level="TRACE"/>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
</root>
<receiver class="ch.qos.logback.classic.net.server.ServerSocketReceiver">
<port>9898</port>
</receiver>
</configuration>
后續(xù)方案實(shí)現(xiàn)過程相對復(fù)雜,就不在這里詳述,另外再找時(shí)間分享給大家
主流方案ETL:Elasticsearch+Logstash+Kibana
- Logstash:日志收集工具,可以從本地磁盤,網(wǎng)絡(luò)服務(wù)(自己監(jiān)聽端口,接受用戶日志),消息隊(duì)列中收集各種各樣的日志,然后進(jìn)行過濾分析,并將日志輸出到Elasticsearch中。
- Elasticsearch:日志分布式存儲/搜索工具,原生支持集群功能,可以將指定時(shí)間的日志生成一個(gè)索引,加快日志查詢和訪問。
- Kibana:可視化日志W(wǎng)eb展示工具,對Elasticsearch中存儲的日志進(jìn)行展示,還可以生成炫麗的儀表盤。