Java日志规范
? ? ? ?前言
一個在生產環境里運行的程序如果沒有日志是很讓維護者提心吊膽的,有太多雜亂又無意義的日志也是令人傷神。程序出現問題時候,從日志里如果發現不了問題可能的原因是很令人受挫的。本文想討論的是如何在Java程序里寫好日志。
一般來說日志分為兩種:業務日志和異常日志,使用日志我們希望能達到以下目標:
Java日志框架
Java的日志框架太多了。。。
選項太多了的后果就是選擇困難癥,我的看法是沒有最好的,只有最合適的。在比較關注性能的地方,選擇Logback或自己實現高性能Logging API可能更合適;在已經使用了Log4j的項目中,如果沒有發現問題,繼續使用可能是更合適的方式;我一般會在項目里選擇使用Slf4j, 如果不想有依賴則使用java.util.logging或框架容器已經提供的日志接口。
3.Java日志最佳實踐
定義日志變量
日志變量往往不變,最好定義成final static,變量名用大寫。
日志分級
Java的日志框架一般會提供以下日志級別,缺省打開info級別,也就是debug,trace級別的日志在生產環境不會輸出,在開發和測試環境可以通過不同的日志配置文件打開debug級別。
在程序里要合理使用日志分級:
1 LOGGER.debug("entering getting content"); 2 String content =CacheManager.getCachedContent(); 3 if(content == null){ 4 5 //使用warn,因為程序還可以繼續執行,但類似警告太多可能說明緩存服務不可用了,值得注意 6 LOGGER.warn("Got empty content from cache,need perform database lookup"); 7 8 Connection conn = ConnectionFactory.getConnection(); 9 if (conn=null) { 10 LOGGER.error("Can't get database connection, failed to return content");//盡量提供詳細的信息,知道錯誤的原因,而不能簡單的寫logger.error("failed") 11 }else{ 12 try{ 13 content = conn.query(...); 14 }catch ( IOException e ){ 15 //異常要記錄錯誤堆棧 16 LOGGER.error("Failed to perform database lookup", e ); 17 }finally{ 18 ConnectionFactory.releaseConnection(conn); 19 } 20 } 21 } 22 //調試的時候可以知道方法的返回了 23 LOGGER.debug("returning content: "+ content); 24 return content;基本的Logger編碼規范
? ? ? ? ? ?1.在一個對象中通常只使用一個Logger對象,Logger應該是static final的,只有在少數需要在構造函數中傳遞logger的情況下才使用private final。
static final logger_LOG=loggerFactory.getLogger(Main.class);?
? ? ? ? ? ? 2.輸出Exceptions的全部Throwable信息,因為logger.error(msg)和logger.error(msg,e.getMessage())這樣的日志輸出方法會丟失掉最重要的StackTrace信息。
void foo(){try {// do something...}catch ( Exception e ){_LOG.error(e.getMessage()); // 錯誤_LOG.error("Bad things : ",e.getMessage()); // 錯誤_LOG.error("Bad things : ",e); // 正確 } }? ? ? ? ? ? ?3.不允許記錄日志后又拋出異常,因為這樣會多次記錄日志,只允許記錄一次日志。
void foo() throws LogException{try{// do something...}catch ( Exception e ){_LOG.error("Bad things : ", e);throw new LogException("Bad things : ",e);} }? ? ? ? ? ? 4.不允許出現System print(包括System.out.println和System.error.println)語句。
void foo() {try{// do something...}catch( Exception e ){ System.out.println(e.getMessage()); // 錯誤System.err.println(e.getMessage()); // 錯誤_LOG.error("Bad things : ",e ); // 正確 }}? ? ? ? ? ? 5.不允許出現printStackTrace。
void foo() {try {// do something...}catch ( Exception e ) {e.printStackTrace(); // 錯誤_LOG.error("Bad things : ", e ); //正確 } }? ? ? ? ? ?6.日志性能的考慮,如果代碼為核心代碼,執行頻率非常高,則輸出日志建議增加判斷,尤其是低級別的輸出<debug、info、warn>。
debug日志太多后可能會影響性能,有一種改進方法是:
if (LOGGER.isDebugEnabled ()) {LOGGER.debug("returning content: "+ content); }但更好的方法是Slf4j提供的最佳實踐:
LOGGER.debug("returning content: {}", content);一方面可以減少參數構造的開銷,另一方面也不用多寫兩行代碼。
7.有意義的日志
通常情況下在程序日志里記錄一些比較有意義的狀態數據:程序啟動,退出的時間點;程序運行消耗時間;耗時程序的執行進度;重要變量的狀態變化。
除此之外,在公共的日志里規避打印程序的調試或者提示信息。
?
FAQ:參考
1.7 Good Rules to Log Exceptions
2.5 common log mistakes
3.Java程序的日志
轉載于:https://www.cnblogs.com/beatIteWeNerverGiveUp/p/5755864.html
總結
- 上一篇: list array解析(总算清楚一点了
- 下一篇: Java回忆录之英勇黄铜V