關於 logger

日誌

前言

我是一名後臺程序員,接觸後臺只有一年時間,在這期間一共作過四個項目,分別是:java

  • 工做室招新系統
  • 視頻學習網站
  • 創客網站
  • 打印機項目

因爲以前作項目的時候沒有好好重視日誌,因此致使在開發與維護項目出現了不少問題,如今分享分享個人慘痛經歷:程序員

  作第一個項目的時候,這個是我第一次開始學習後臺時作的第一個項目,使用最原始的 servlet + jsp 技術,當時沒有任何經驗,沒有把系統的需求和實現方式思考清楚就開始動工,作的過程遇到不少問題,但今天的主題不在這些問題上,而是關於日誌,當時咱們並無在項目使用日誌技術記錄日誌信息,由於該項目沒有進行上線發佈,因此後面作完了大部分功能以後就沒繼續完善和維護,因此沒有意識到日誌的重要性。 
  作第二個項目與第三個項目時,這是一個商業項目,因爲第一次沒有意識到日誌的重要性,因此開發時是沒有打日誌的,等到項目開發完後,咱們須要上線測試,部署到服務器時,發現出現了不少個 bug,但之前咱們找 bug 都是經過調試或者在控制檯輸出錯誤信息來查看,部署到服務器上根本調試不了也看不到錯誤信息,這就致使一直找不到致使出現 bug 的地方。後面在項目添加了,但只是在 servlet 層後面添加一個全局的try catch,再記錄錯誤信息而已,但這並沒起多大做用。 
  作第四個項目時,當時有要打日誌的想法,可是因爲以前沒作過,因此對於要如何打日誌根本不理解,應該在什麼地方記錄日誌,應該使用哪一種日誌級別。因此最後在項目的時候就隨便亂打日誌,致使最後輸出的日誌信息時,也是一團亂。數據庫

在基於前面的經歷,以爲有必要去好好學習如何使用日誌機制。服務器

爲何要使用日誌機制

  就如我以前所說的,開發之後應用服務時,若是你沒有使用日誌機制,那麼當你將服務部署上去時,系統出 bug 了,由於沒有錯誤信息能夠查看,因此你找不到錯誤出現的地方,這樣會不方便測試與維護。使用日誌及時記錄錯誤的信息,會更方便咱們定位到錯誤的地方以及錯誤的緣由,方便咱們修復系統。併發

日誌機制

日誌信息級別

日誌信息通常有五種級別,分別是:app

  • DEBUG 
    DEBUG 級別是最低的級別,通常是爲了用於測試應用程序而輸出日誌信息,它只能用於開發環境與測試環境,不能用於線上環境。異步

  • INFO 
    INFO 級別比 DEBUG 級別要高,通常用此級別來記錄服務正在開啓、從請求接收的信息、響應返回的信息等等jsp

  • WARN 
    WARN 級別 比 INFO 級別要高,通常是用於記錄客戶端與服務端鏈接丟失,數據庫鏈接丟失、Scoket 鏈接達到限制等一些表示 server 運行時的狀態信息函數

  • ERROR 
    ERROR 級別 比 WARN 級別要高,通常是用於記錄系統出現錯誤的異常錯誤信息,在開發時候,經過記錄 ERROR 級別的信息,能夠方便地定位到系統出錯的地方,從而更方便地修復系統高併發

  • FATAL 
    FATAL 級別的信息通常是用於記錄很是嚴重的錯誤事件信息,該事件可能會致使應用崩潰或者中止

如何使用日誌

  • 在輸出 DEBUG 級別的日誌信息前加一層 isDebugEnabled() 的判斷,由於這是爲了不繫統發佈到運行環境上以後輸出過多的日誌信息,也避免須要爲了發佈而刪掉或註釋掉輸出的 DEBUG 信息,由於這會影響往後的系統維護
  • 認真考慮好哪些信息要用哪一種級別去記錄日誌。若是在發佈環境上記錄太多日誌信息會影響性能,由於這會產生不少文件 IO ;但若是不記錄重要的信息如接收的信息、響應的信息,將會很是困難找出錯誤的問題和異常在何處
  • 使用配置文件來加載日誌的信息,這會方便地改變系統的日誌記錄級別,從而避免重啓應用
  • 對於記錄的日誌信息,須要格式化;在高併發的系統時,須要記錄當前的線程名以及當前處理類的徹底限定名;記錄的日誌格式應一致、有用,必要的時候還要輸出時間
  • 使用一系列後綴來區分不一樣的層次的信息。好比與數據庫有關,就記錄 DB_LOG,與 Session 有關,記錄 SESSION_LOG,這樣有利於經過後綴查找匹配出那個層次的全部日誌信息,方便管理和差錯
  • 若是沒有爲一個日誌指定級別,應該讓他從他的父類繼承,因此咱們通常經過配置文件爲根日誌配置級別爲 DEBUG
  • 沒有日誌或過多的日誌都是很是很差的,因此在性能和維護差錯方面作好一個平衡,仔細選擇要用哪些級別記錄哪些信息
  • 記錄的日誌信息應當是簡單、易懂而且對於團隊來講是有效的

Log4j

爲系統性能考慮,使用 Log4j 注意下列幾點:

  • 避免輸出 ‘%C’, ‘%f’, ‘%L’, ‘%M’ 等位置信息
  • 儘可能使用異步
  • 爲每一個模塊設置單獨的輸出文件
  • 每次調用前檢查 if(logger.isDebugEnabled()) { logger.debug(……) }

解析:

  1. 避免輸出 ‘%C’, ‘%f’, ‘%L’, ‘%M’ 等位置信息 
    當配置文件中的配置項包含 Location 信息會很是昂貴 
    • %C 輸出類名
    • %F 輸出文件名
    • %L 輸出行號
    • %M 輸出函數名

注:當配置爲異步輸出的時候,以上位置信息可能會顯示不出來,由於實在另外的一個線程記錄的調用信息。此時,咱們可使用下面的方法來獲取類名和函數名:

StackTraceElement se = Thread.currentThread().getStackTrace()[2];
String msg = se.getClassName() + "-[" + se.getMethodName() + "] " + errorMessage;
  1. 使用異步 
    要使用異步在於要在配置文件中配置 appender,爲何要使用異步來記錄日誌,前面說過記錄日誌信息會產生文件 IO,這會影響必定的性能,使用異步能夠避免由於須要同步記錄日誌而產生的等待時間。

  2. 爲每一個模塊設置單獨的輸出文件 
    根據模塊來區分日誌文件,在調試和維護某個模塊時,能夠更方便。

  3. 每次調用前檢查 if(logger.isDebugEnabled()) { logger.debug(……) } 
    前面已說過

總結

  日誌機制對於開發來講是很是重要的,它關係到調試與維護,在開發一個項目前期,應該提早部署好日誌環境。同時,在開發的過程當中,要想好如何去記錄日誌信息,要用哪一種級別去記錄,權衡性能與維護,選擇一種較好的日誌實施方案。

本文只是我的觀點,若有不一樣意,能夠說出來你們一塊兒討論討論。以後再補充一篇使用 slf4j + logback 搭建日誌機制的博文。

相關文章
相關標籤/搜索