1. 程式人生 > >java 日誌體系概述與應用

java 日誌體系概述與應用


1.常見的日誌列印元件有:

  • log4j
  • logback
  • log4j2
  • java.util.looging

2.Apache Commons Loging (JCL)

Commons Loging 本身只提供日誌介面,具體實現在執行時動態尋找對應元件?比如:log4j、jdk14looger 等。但這種動態繫結的方式當系統特別寵大的時候會出現繫結失敗的問題。現在比較流行的slf4j 基於靜態繫結的方式解決了這個問題。

3.slf4j

sl4j 本身也只提供日誌介面,與commons loging 不同的是其採用在classPath 加入以下jar包來表示具體採用哪種實現 :

  • slfj-log4j12.jar (表示指定 log4j)
  • slf4j-jdk14.jar(表示指定jdk Looging)
  • slf4j-jcl.jar(表示指定jcl)
  • log4j-slf4j-impl(表示指定log4j2)
  • logback-classic(表示指定logback)

假設你們系統當中之前在用 JCL 列印日誌,但這時想加入slf4j來列印日誌,就會出現兩類日誌,解決辦法是加入如下等JAR包jcl-over-slf4j、log4j-over-sl4j、jul-over-sl4j ,即可在使用原API的情況下,又統一至slf4j 的實現進行輸出了。

其他日誌輸出轉換slf4j示例圖如下:

總結下各個日誌元件的對應關係:

JAVA日誌體系結構圖

4.log4j2使用

log4j2是目前非同步輸出效能最好的日誌元件

4.1 安裝/引入

在pom.xml中加入依賴

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.10.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.10.0</version>
</dependency>

4.2 配置檔案

Log4j 2.x配置檔案只能採用.xml, .json或者 .jsn,不能使用1.x中的properties檔案。 

程式從classpath下尋找配置檔案的優先順序如下: 

log4j-test.json 或者log4j-test.jsn檔案 > log4j2-test.xml > log4j.json 或者log4j.jsn檔案 > log4j2.xml

配置檔案的結構

Configuration
    --Appenders
        --Child(輸出型別)
            --Layout(輸出的模板)
            --Filters(日誌過濾器)
    --Loggers
        --Logger(日誌輸出物件)
            --Appender-ref(引用上面定義的輸出型別)

配置檔案模板

<?xml version="1.0" encoding="UTF-8"?>
<!--
    status : 這個用於設定log4j2自身內部的資訊輸出,可以不設定或設定為OFF;當設定成trace時,會看到log4j2內部各種詳細輸出。
    monitorInterval : Log4j能夠自動檢測修改配置檔案和重新配置本身, 設定間隔秒數。此處表示每隔600秒重讀一次配置檔案
-->
<configuration status="OFF" monitorInterval="600">
    <Properties>
        <!-- 設定屬性,相當於全域性變數 -->
        <Property name="LOG_HOME">logs</Property>
        <Property name="DEBUG_FILE_NAME">debug</Property>
        <Property name="ERROR_FILE_NAME">error</Property>
        <Property name="ROLL_FILE_NAME">rollingLog</Property>
    </Properties>
    <appenders>
        <!-- target是指定輸出的目標,預設為System.out,也可以設定成System.err -->
        <Console name="STDOUT" target="SYSTEM_OUT">
            <ThresholdFilter level="TRACE" onMatch="ACCEPT" onMismatch="DENY"/>
            <!-- 輸出內容的樣式、模板 -->
            <PatternLayout
                pattern="%d{HH:mm:ss.SSS} %-5level [%t] %C %M %L - %msg%xEx%n" />
        </Console>
        <File name="DEBUG" fileName="${LOG_HOME}/${DEBUG_FILE_NAME}.log"
            append="false">
            <PatternLayout
                pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n" />
        </File>
        <File name="ERROR" fileName="${LOG_HOME}/${ERROR_FILE_NAME}.log"
            append="true">
            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout
                pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n" />
        </File>
        <!-- 
            fileName : 指定當前日誌檔案的位置和檔名稱
            filePattern : 指定當發生Rolling時,檔案的轉移和重新命名規則
            SizeBasedTriggeringPolicy : 指定當檔案體積大於size指定的值時,觸發Rolling
            TimeBasedTriggeringPolicy : 這個配置需要和filePattern結合使用
            DefaultRolloverStrategy : 指定最多儲存的檔案個數

                    注意filePattern中配置的檔案重新命名規則是${ROLL_FILE_NAME}_%d{yyyy-MM-dd}_%i,最小的時間粒度是dd,即天,
                    TimeBasedTriggeringPolicy指定的size是1,結合起來就是每1天生成一個新檔案
         -->
        <RollingFile name="RollingFile" fileName="${LOG_HOME}/${ROLL_FILE_NAME}.log"
            filePattern="${LOG_HOME}/${ROLL_FILE_NAME}_%d{yyyy-MM-dd}_%i.log">
            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout
                pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n" />
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="false" />
                <SizeBasedTriggeringPolicy size="1 MB" />
            </Policies>
            <DefaultRolloverStrategy max="100"/>
        </RollingFile>
        <!--配置非同步寫日誌-->
        <Async name="Async">
            <AppenderRef ref="ALL"/>
        </Async>
        <!--輸出到MongoDB中-->
        <NoSql name="databaseAppender">
            <MongoDb databaseName="test" collectionName="errorlog" server="localhost" port="27017" />
        </NoSql>
    </appenders>
    <loggers>
        <logger name="STDOUT">
            <appender-ref ref="STDOUT"/>
        </logger>
        <logger name="ROLLLOG" additivity="false">
            <appender-ref ref="RollingFile"/>
        </logger>
        <root level="trace">
            <appender-ref ref="RollingFile"/>
            <appender-ref ref="ERROR" />
        </root>
    </loggers>
</configuration>

輸出型別

  • Appender 設定在哪輸出日誌資訊 
  • FileAppender 普通地輸出到本地檔案 
  • FlumeAppender 將幾個不同源的日誌彙集、集中到一處。 
  • JMSQueueAppender VS. JMSTopicAppender 與JMS相關的日誌輸出 
  • RewriteAppender 對日誌事件進行掩碼或注入資訊 
  • RollingFileAppender 對日誌檔案進行封存(詳細) 
  • RoutingAppender 在輸出地之間進行篩選路由 
  • SMTPAppender 將LogEvent傳送到指定郵件列表 
  • SocketAppender 將LogEvent以普通格式傳送到遠端主機 
  • SyslogAppender 將LogEvent以RFC 5424格式傳送到遠端主機 
  • AsynchAppender 將一個LogEvent非同步地寫入多個不同輸出地 
  • ConsoleAppender 將LogEvent輸出到命令列 
  • FailoverAppender 維護一個佇列,系統將嘗試向佇列中的Appender依次輸出LogEvent,直到有一個成功為止

1,Console Appender 

把資訊輸出結果控制檯。 

2,File Appender 

輸出結果到指定檔案。 

3,Rolling File Appender 

自動追加日誌資訊到檔案中,直至檔案達到預定的大小,然後自動重新生成另外一個檔案來記錄之後的日誌。

日誌級別

TRACE < DEBUG < INFO < WARN < ERROR < FATAL 

輸出資訊為>=當前設定級別的資訊,因此TRACE的資訊是最大的。

過濾器

log4j2有多種過濾器,最簡單的是Threshold過濾器,其有三個配置項

配置項 描述
level 最低的輸出日誌級別
onMatch ACCEPT/DENY/NEUTRAL,匹配時是否輸出日誌或由後面的過濾器決定
onMismatch ACCEPT/DENY/NETURAL,不匹配時是否輸出日誌或由後面的過濾器決定

log4j2 logger 載入規則

  1. logger name 相同時,以 level 級別高的為準
  2. logger name=”org” 會被 name=”org.xxx” 繼承,”root”預設被所有logger繼承。
  3. logger 中的 additivity=”true” 表示子日誌所獲得的日誌也會在父日誌中出現,即使父日誌的 level 遠高於子日誌的 level
  4. 當子日誌 level 大於父日誌時,父日誌只能接收到子日誌過濾後的日誌

程式碼中使用

private static Logger logger = LogManager.getLogger("STDOUT");

模板樣式

可用的轉換字元詳解: 

常用的有:

轉換字元 表示的含義
c 用於輸出的記錄事件的類別。例如,對於類別名稱”a.b.c” 模式 %c{2} 會輸出 “b.c”
C 用於輸出呼叫者發出日誌請求的完全限定類名。例如,對於類名 “org.apache.xyz.SomeClass”, 模式 %C{1} 會輸出 “SomeClass”.
d 用於輸出的記錄事件的日期。例如, %d{HH:mm:ss,SSS} 或 %d{dd MMM yyyy HH:mm:ss,SSS}.
F 用於輸出被髮出日誌記錄請求,其中的檔名
l 用於將產生的日誌事件呼叫者輸出位置資訊
L 用於輸出從被髮出日誌記錄請求的行號
m 用於輸出使用日誌事件相關聯的應用程式提供的訊息
M 用於輸出發出日誌請求所在的方法名稱
n 輸出平臺相關的行分隔符或文字
p 用於輸出的記錄事件的優先順序
r 用於輸出毫秒從佈局的結構經過直到建立日誌記錄事件的數目
t 用於輸出生成的日誌記錄事件的執行緒的名稱
x 用於與產生該日誌事件的執行緒相關聯輸出的NDC(巢狀診斷上下文)
X 在X轉換字元後面是鍵為的MDC。例如 X{clientIP} 將列印儲存在MDC對鍵clientIP的資訊
% 文字百分號 %%將列印%標誌