Java日誌架構介紹__Java

來源:互聯網
上載者:User
概述

在剛接觸日誌架構時,被很多日誌架構搞的頭暈,下面將整體介紹下當前流行的開源日誌架構,並重點介紹log4j的日誌輸出原理及配置指導

日誌架構 簡介 參考
JUL JDK內建日誌架構(java.util.logging),由於效率及靈活性較差,目前使用的較少 http://docs.oracle.com/javase/1.5.0/docs/guide/logging/overview.html#1.0
JCL Apache Common-Logging是apache開源的日誌介面系統,在java系統中,有多種的日誌實現方式,該架構僅提供日誌輸出介面,在實際運行時,根據應用需要,靈活切換日誌實現; 在slf4j日誌介面出現之前,採用JCL+log4j實現記錄項目較多;但該架構有個致命的問題:在OSGI這樣的架構無法正常工作 http://commons.apache.org/proper/commons-logging/index.html
Slf4j 也是一種日誌介面系統,類似JCL,但相比JCL,其可以在OSGi這樣的架構上完美運行,該架構作者,實現了log4j/logback http://www.slf4j.org/
Log4j 使用最為廣泛的一個日誌架構系統,通過控制設定檔,我們可以方便的按特定的格式,將日誌輸出至控制台、檔案、遠程Log Service器,支援檔案的自動切換備份 http://logging.apache.org/log4j/1.2/
Logback 該架構與log4j架構作者是同一個人,由於其調整了實現架構,輸出日誌效能高於Log4j,且其支援自動備份壓縮,該架構作者極力推薦使用Logback替換Log4j http://logback.qos.ch/

由上表總結我們可以看到,如後續有新項目,建議採用slf4j+logback實現,但由於多方面原因,目前log4j使用依然較普遍,下面將重點介紹log4j log4j日誌輸出原理

log4j(log for java)主要是通過三個類來完成日誌的輸出:Loggers, Appenders and Layouts

Loggers:用於輸出日誌的執行個體 1】Logger之間存在父子關係,預設子Logger對應的日誌輸出請求會同時列印至所有的父Logger中

例如有兩個類:com.ucweb.account.sdk.TestA,com.ucweb.account.TestB,且設定檔中配置了對應的log4j.logger.com.ucweb.account.sdk/log4j.logger.com.ucweb.account類TestA對應通過org.apache.log4j.Logger.getLogger(Class clazz)擷取對應的LoggerA;TestB對應通過org.apache.log4j.Logger.getLogger(Class clazz)擷取對應的LoggerB,則LoggerA的父Logger就是LoggerB, 而LoggerA和LoggerB的根Logger就是RootLogger
2】可以通過自訂logger名稱,然後通過getLogger(String name)擷取對應執行個體 3】唯一的RootLogger,每個應用都應該配置一個RootLooger,它是所有其它Logger的根,如未配置對應的Logger,則其日誌預設全部列印至RootLogger

Appenders:使用者定義最終日誌輸出的目標:控制台、檔案、遠程伺服器

最常用:org.apache.log4j.ConsoleAppender/org.apache.log4j.RollingFileAppender

Layouts:定義日誌輸出格式:時間戳記、線程名稱、記錄層級、日誌內容、對應輸出該日誌的類、對應輸出該日誌的方法、行號及MDC資訊

最常用:org.apache.log4j.PatternLayout

三者之間的關係:


每個logger可以配置多個Appender,每個Appender對應一個Layout,在輸出日誌時,會依次將日誌內容按照Layout的格式輸出對應的Appender上
目前jws架構中的使用方式 jws是從playframework架構演變而來,playframework 1.x版本是使用:slf4j+log4j; 2.x版本切換至slf4j+logback jws對外提供的日誌介面jws.Logger,其主要提供兩類輸出介面方式:
 debug/info/warn/error/fatal:這類介面日誌預設統一輸出到jws.log記錄檔 event:這類介面日誌預設輸出至由event指定的logger名稱上,例如event("error","msg info"),將輸出值error.log中;

【缺點】:

 1)使用非event方式輸出日誌,所有日誌都輸出到jws.log,在多個線程同時輸出日誌時,存在資源競爭; 2)使用event方式雖然可以解決問題1),但該方式無法輸出對應日誌輸出類及方法資訊; 3)目前jws架構,預設提供的日誌輸出Layout是不列印“線程名+類資訊+方法資訊+日誌出錯行資訊”,非常不利於定位問題;
log4j配置

配置方式: log4j可以通過properties/xml兩種方式配置(僅檔案格式不同),建議用properties檔案編寫對應配置項,下面給出一個日誌配置樣本:


#對一個應用來說,必須要有一個rootLooger#所有的Logger配置對應的value值都是類似:層級,Appender-1[,Appender-2,...,Appender-n];#其中層級取值:all,debug,info,warn,error,fatal,off,建議使用:info,warn,error這三個層級#其中Appender-x,必須是一個存在與當前設定檔的Appenderlog4j.rootLogger=warn,rootAppender #對應的Appender類別log4j.appender.rootAppender=org.apache.log4j.RollingFileAppender#如下的屬性像是與具體的Appender類別相關#記錄檔路徑,相對與當前程式運行目錄log4j.appender.rootAppender.File=logs/root.log#單個記錄檔大小-最大值,下面配置表示:root.log檔案大小超過20M後就會自動備份root.log.1,然後重寫新檔案log4j.appender.rootAppender.MaxFileSize=20MB#備份檔案最大個如,下面配置表示:備份檔案達到100個後,自動清除最老的檔案log4j.appender.rootAppender.MaxBackupIndex=100#Layout類別log4j.appender.rootAppender.layout=org.apache.log4j.PatternLayout#下面的配置屬性,與具體的Layout類別相關#%d{yyyy-MM-dd HH:mm:ssS}      按對應格式輸出時間資訊;#%p 記錄層級#[%t] 對應線程名稱#%m 對應日誌內容#%c  對應輸出該日誌的類#%L 對應輸出該日誌所在類對應的行號log4j.appender.rootAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ssS} %-5p [%t] %m (%.30c.%L)%n #自訂loggerlog4j.logger.com.ucweb.profile=warn,perfmt#僅列印日誌到當前檔案開關,不遞迴列印至父Logger中#這個開關預設是開啟(遞迴打日誌到父Logger),強烈建議業務關閉這個開關;log4j.additivity.com.ucweb.profile=false# Rolling fileslog4j.appender.perfmt=org.apache.log4j.RollingFileAppenderlog4j.appender.perfmt.File=logs/monitor.loglog4j.appender.perfmt.MaxFileSize=20MBlog4j.appender.perfmt.MaxBackupIndex=100#如配置了Threshold這個屬性項,它表示該Appender輸出日誌時,對應的層級閾值,#log4j先校正logger對應的記錄層級,然後才使用Threshold對應的記錄層級,為防止配置出錯,建議非特殊情況,不要配置該屬性項#log4j.appender.perfmt.Threshold=info#這個配置項表示是否立即重新整理日誌內容到磁碟,預設是開啟的,建議採用預設值#log4j.appender.perfmt.immediateFlush=truelog4j.appender.perfmt.layout=org.apache.log4j.PatternLayoutlog4j.appender.perfmt.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ssS} %-5p [%t] %m (%.30c.%L)%n #控制台log4j.appender.console=org.apache.log4j.ConsoleAppenderlog4j.appender.console.layout=org.apache.log4j.PatternLayoutlog4j.appender.console.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss}] %p ~ %m%n

載入方式: 啟動階段載入:

通過添加系統內容變數: log4j.configuration=指向對應log4j設定檔的url
運行過程中載入:
1)程式啟動入口處,通過PropertyConfigurator.configure(),動態載入log4j設定檔;2)Log4j自身支援定時檢查設定檔是否修改,如修改會自動重新載入;3)代碼中通過log4j提供的API,修改對應記錄層級

注意事項: 1)每個獨立的業務(或子系統)應獨立一個Logger,每個Logger獨立寫記錄檔,這樣各自業務日誌相互獨立,即方便問題定位,有提升Tlog效率

簡單起見在編碼設計階段就通過包名做區分,比如如下業務:論壇:com.ucweb.bbs   發號:com.ucweb.ka  門戶:com.ucweb.game;這樣在設定logger時,通過如下配置,對應所有該包下的類預設都只輸入到各自業務記錄檔中:

#BBS日誌log4j.logger.com.ucweb.bbs=warn,bbsAppenderlog4j.additivity.com.ucweb.bbs=falselog4j.appender.bbsAppender=org.apache.log4j.RollingFileAppenderlog4j.appender.bbsAppender.File=logs/bbs.loglog4j.appender.bbsAppender.MaxFileSize=20MBlog4j.appender.bbsAppender.MaxBackupIndex=100log4j.appender.bbsAppender.layout=org.apache.log4j.PatternLayoutlog4j.appender.bbsAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ssS} %-5p [%t] %m (%c.%L)%n#發號日誌log4j.logger.com.ucweb.ka=warn,kaAppenderlog4j.additivity.com.ucweb.ka=falselog4j.appender.kaAppender=org.apache.log4j.RollingFileAppenderlog4j.appender.kaAppender.File=logs/ka.loglog4j.appender.kaAppender.MaxFileSize=20MBlog4j.appender.kaAppender.MaxBackupIndex=100log4j.appender.kaAppender.layout=org.apache.log4j.PatternLayoutlog4j.appender.kaAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ssS} %-5p [%t] %m (%c.%L)%n #門戶日誌log4j.logger.com.ucweb.game=warn,gameAppenderlog4j.additivity.com.ucweb.game=falselog4j.appender.gameAppender=org.apache.log4j.RollingFileAppenderlog4j.appender.gameAppender.File=logs/game.loglog4j.appender.gameAppender.MaxFileSize=20MBlog4j.appender.gameAppender.MaxBackupIndex=100log4j.appender.gameAppender.layout=org.apache.log4j.PatternLayoutlog4j.appender.gameAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ssS} %-5p [%t] %m (%c.%L)%n
2)關閉遞迴向父Logger中列印日誌,通過log4j.additivity配置 3)配置Layout時,盡量輸出如下資訊:時間戳記,線程名,類,方法,日誌內容,行號; 4)線上環境禁止輸出日誌至控制台Appender; 5)線上環境,記錄層級組號是warn以上層級; 日誌列印注意事項

目前jws架構是通過slf4j日誌介面對外提供日誌輸出,建議輸出日誌時,遵守如下日誌編碼規範:

規則1】非特殊情況下,擷取日誌樣本統一用slf4j的LoggerFactory如下籤名方法擷取,目的是為了方便後續切換日誌實現,同時也統一編碼風格:


 org.slf4j.LoggerFactory 對應如下籤名方法: public static Logger getLogger(Class clazz) 且對應的日誌執行個體最好定義成static final private static final Logger logger = LoggerFactory.getLogger(LogDemo.class);

規則2】禁止在列印日誌代碼中,摻雜商務邏輯操作,特別是修改快取作業:下面樣本中logicMap是業務緩衝,編碼者本意是想刪除緩衝中一元素,並通過日誌做記錄。但當系統記錄層級調整為warn以上時,remove操作將不執行,這將產生致命性錯誤,且難定位


logicMap.put("danger", "danger");if(logger.isWarnEnabled()){     logger.warn("rmv a value:{}", logicMap.remove("danger"));}

規則3】對吃掉異常的,一定要列印詳細堆棧資訊(特殊無需列印,需要代碼中添加註釋),如僅對異常做封裝,之後再次向外拋出,則禁止列印堆棧資訊,最多列印簡單的定位資訊即可;異常資訊,必須用error層級列印:


        try {            //可能拋出異常的邏輯        } catch (Exception e) {            //此處吃掉異常,需要將異常堆棧列印出來            logger.error("", e);        }

規則4】在迴圈中直接輸出日誌資訊,可以先通過StringBuilder(非StringBuffer)做日誌收集操作,然後一次性輸出日誌,如待輸出日誌內容過長,需要做截斷處理


        StringBuilder sb = new StringBuilder();        String[] businessTmp = new String[BUS_LEN];        for (

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.