top 10 tipis on Logging in Java- Tutorial (翻譯)

開篇廢話,就記得出國以前有一回騰訊面試,面試官說既然你都快要出國了,英語確定挺不錯的,那爲何不去翻譯一些國外好的文章呢,我但願找一個能主動學習的人,一直受教。目前在實習,須要作大數據相關方向,都是挺前衛的東西,發現國內的資料有點稀缺,hadoop官網啥的都是英文,硬着頭皮開始啃這些,發現國外的技術想法真的挺不錯的,用英文找資料也得卻方便。我把我作的過程當中找到的一些不錯的文章都保存下來,github項目地址,感興趣的能夠去fork或者star一個,絕大部分都是英文,若是英語不錯的能夠直接看,都是不錯的文章。html

______________________________________________________java

Java 日誌或者說用 JAVA 記錄日誌是一門學問也是一門藝術。 知道日誌記錄工具和 API 是一門技術,可是選擇日誌格式,消息格式,記錄內容,日誌級別更像來自經驗的總結。由於 Java日誌會很是影響性能,我見證了線上股票交易系統由於 DEBUG 模式比 WARN 或者更高的日誌級別帶來的延遲, 在線交易系統中,延遲和響應速度是很是重要的因素,尤爲是對於股票交易系統。正由於此,系統的瞭解 Java 日誌是很是有必要的, 不只僅是對於金融和銀行投資系統,並且對於任何的追求響應速度和完備的日誌的 java 服務器或者客戶端應用.linux

在這一篇 Java 日誌總覽中,我會分享我在 Java 日誌方面的經驗,我會回答一些基礎的問題「爲何須要 Java 日誌」,「不一樣的 Java 日誌級別以及如何選擇正確的日誌級別」,「不正確的 Java 日誌如何影響了性能」。 我會討論一些 Java 日誌工具和 API, 例如 log4j.jar 和Java.util.logging.git

爲何須要 JAVA 日誌程序員

這是一個很基礎的關於 Java 日誌的問題,你們都說反正已經有 System.out.println()來打印記錄了,爲何還須要 logging。咱們都是從 System.out.println()打印消息(」Hello World!」)到終端上,開始的 Java 學習之旅。可是這個遠不能和功能強大的 Java 日誌 API(好比 log4j 和java.util.logging)相比。 若是你開發一個 Java 服務器端應用,若是你不記錄任何運行信息,你就不可能知道你的服務器正在幹什麼。這對於須要不少上傳信息和下載信息(信息交換)的應用來講(例如股票交易和在線交易系統),記錄日誌顯得更爲重要。若是不記錄日誌,你壓根不知道哪裏出了問題。這就是爲何 Java 日誌服務在 Java 服務端應用中很重要,並且是必須的。github

Java 日誌的不一樣級別面試

用過 Java 日誌的必定知道 Java 日誌級別, 例如 DEBUG, INFO, WARN 和 ERROR. 數據庫

DEBUG 是最低限制級的日誌級別,而且咱們須要記錄全部的日誌去調試代碼,這個模式只能在開發和測試環境中使用,不能在生產環境中使用。編程

INFO 是比 DEGUG 更限制的日誌級別, 咱們只應該記錄一些重要的信息內容,例如服務器啓動,有請求,輸入輸出數據等等。緩存

WARM 是比 INFO 更限制的日誌級別,主要是用來記錄警告信息,包括服務器和客戶端斷開鏈接,數據庫斷開鏈接, socket 到達限制。 這些信息是頗有用的,你能夠在此基礎上監控你的服務器運行狀態並對這些警告信息作出反應。

ERROR 是比 WARN 更限制的日誌級別,它是用來記錄錯誤和 Exception 的,你能夠 alert(彈出)這些錯誤信息,你必須牢記打印出 ERROR 的錯誤信息。

FATAL 是用來記錄很嚴重的錯誤信息,這些錯誤通常會致使服務器奔潰或者宕機。

OFF 級別表明了要關閉 Java Logging 功能。

這些日誌級別是定義在 log4j 包的基礎上,跟 java.util.logging API 區別也不大, java.util.loggingAPI 還額外提供例如 SEVERE,FINER,FINEST,FATAL 等其餘級別。上述的那些級別是最經常使用的。

                                            使用 log4j 或者 java.util.loggin API 來作日誌記錄

我會推薦使用 log4j 來作 java 日誌記錄,你可能會有疑問,爲何不使用 java.util.logging. 我贊成 java.util.logging 功能很是強大, 可是 log4j 更直觀和易於使用,你已經看到了基於 log4j 的日誌級別很是的清晰,另外在 log4j 中你不須要爲了改變日誌級別而重啓服務,固然你用java.util.logging 也能夠作到,前提是你已經使用 JMX 實現這個功能了。

Log4j 能夠在 log4j.xml 的基礎上輕鬆的設置每一個類的日誌級別,你能夠選擇使用log4j.properties file 或者 log4j.xml 來配置日誌信息,並且 log4j 是線程安全的, log4j 是被設計用於繁忙的多線程系統中的,在另外一方面,我發現 java.util.logging 中的 Formatter 和 Appender 很是有用,由於它能夠格式化你要打印的東西。

日誌記錄怎麼影響 java 性能的

Java 日誌服務對你的應用性能能產生很嚴重的影響, 你打印的日誌越多, IO 消耗就越多, 對你的性能影響就越大。 這就是爲何選擇正確的日誌級別是很重要的。 你要作的就是控制日誌的級別和信息。 因此把 DEBUG 信息放在 isDebugEnabled()塊內, 下面的代碼就是一個很好的例子。

 

if(logger.isDebugEnabled()){
logger.debug("java logging level is DEBUG Enabled");
}

在正式環境中使用 WARN ERROR 或者 FINER, FINEST 這樣的日誌級別, 絕對不要使用 DEBUG 在正式環境中, 我見過一些應用運行起來很是慢的緣由就是由於有 DEBUG 級別的日誌在打印。

在 JAVA 日誌服務中的 10 個小細節

1) 使用 isDebugEnabled()未來輸出 DEBUG 日誌, 它會節省不少的字符串鏈接操做當你轉換到正式環境中。 {這裏是由於正式環境中, 都不須要執行這段代碼了, 因此不會有日誌輸出,固然節省了不少的字符串鏈接操做}。

2) 仔細的選擇你的日誌級別和打印日誌的位置, 日誌不宜過多, 由於會影響性能, 也不宜過少, 由於過少的日誌信息很難讓你定位到錯誤位置和你須要的關鍵信息。

3) 建議使用 log4j.xml, 由於我用過它不少次, 我發現它很靈活, 它能讓你改變日誌級別而不須要重啓服務, 這在環境轉換中是很是有用的(從調試環境到正式環境), 它是經過 log4jwatchdog( 看門狗) 程序一直在監視 log4j.xml,若是找到它就加載而後從新設置日誌級別。

4) 經過使用 log4j.xml,你能夠對不一樣的 java 類設置不一樣的日誌級別, 這是很是靈活的。

5) 另外一個重要的點是, 記住日誌格式, 在日誌中最好包括進程名字和類名, 方法名, 這會幫你很方便的定位。

6) 仔細選擇日誌格式, 你能夠經過它生成報表。 Balabala 一堆。

7) 在你生成日誌的時候, 能夠在日誌的開頭使用一些特殊的標記, 例如方便定位到 client side,database side, session side 等, 由於接下來你能夠在 linux 環境下使用 grep 或者 find 命令很方便的找到相關的信息。 例如你能夠加一個標記「 DB_LOG」 針對於有關數據庫的日誌,「 SESSION_LOG」 針對有關於緩存的信息。

8) 假如你沒用定義一個日誌級別, 那麼它會自動的是使用離他最近的一個錨, 這就是爲何咱們常常定義 root 日誌級別爲 log4j.rootLogger = DEBUG.

9) 沒有日誌和過多的日誌都是壞主意, 因此仔細選擇你想要打印的內容並選好日誌級別, 這樣能讓你在正式環境中快速的運行應用, 同時讓你在開發環境中很快的找到問題。

10) 優化你的日誌是很重要的, 日誌要保持簡單和明瞭, 不僅僅是爲了本身, 也爲了方便別人查看和更改。

11) 若是你是使用 SJFS 來記錄 java 日誌的, 那麼使用參數模式可讓你性能變得更快,

logger.debug("No of Orders " + noOfOrder + " for client : " + client); // slower
logger.debug("No of Executions {} for clients:{}", noOfOrder , client); // faster

 

這裏做者也不知道爲何, 實際上是由於第二種模式少了字符串拼接過程, 因此變的更快了。 後面的連接中有給出, 你們能夠看看。

更新:

記錄日誌的好壞能夠用來區分好的程序員和偉大的程序員。 不只僅是對於 JAVA,對於其餘編程語言也是同樣的。 你須要關注的是:

1) 你須要打印什麼樣的信息?

2) 這個信息是屬於哪一個日誌級別的?

這是兩個最重要的問題, 下面是我編程的一些寶貴經驗:

1) 不要打印敏感信息, 包括密碼, 社會人口號, 信用卡帳號等等, 在你完成這部分開發的時候就應該把這些可能打印出來的關鍵信息刪除了。

2) 打印一些決策性的信息, 好比你在 java 中加載一些配置信息, 若是沒找到就加載默認選項,那你能夠打印如下內容:

logger.info("Not able to load personal settings, default Setting selected for user : {user});

這裏就包括決策性信息, 並且也包括了哪一個用戶信息你無法打印, 由於你可能擁有不少個用戶。

3) 保持一致性, 日誌格式須要保持一致。

4) 打印關鍵信息, 尤爲是你在調試的時候。

咱們常常用到日期轉換成字符串的操做, 這個方法常常會拋出一些異常, 如下就是一個日誌,這個打印信息包含的內容不全, 它沒有告訴咱們究竟是什麼問題, 是輸入的日期格式不對, 日期空白, 仍是什麼。

logger.info("failed to convert String to date");

這個打印日誌語句就行了不少, 它告訴了咱們輸入的究竟是什麼東西, 咱們能夠很容易的定位出問題位置和問題緣由。 logger.info("invalid startDate : {startDate});

感謝你閱讀本篇文章, 若是你以爲不錯, 歡迎分享給你的朋友。

_________________________________________________________

第一次翻譯文章,有些地方都只是意會,沒有翻譯原文的意思。github上有英文原版,能夠直接去閱讀,附錄裏面的幾篇文章都挺不錯的,看完基本就弄明白,透徹了。

——————————————————————————————————
最後面是我找到的幾篇 JAVA 日誌級別的文章
http://developer.51cto.com/art/201507/484646.htm Java 日誌終極指南
http://www.ibm.com/developerworks/cn/java/j-lo-practicelog/index.html#ibm-pcon Java 日誌管理
最佳實踐
http://www.oschina.net/translate/why-use-sl4j-over-log4j-for-logging?cmp 爲何使用 SLF4J 而不
是 Log4J 來作 Java 日誌( 這是原做者寫的關於 java 日誌的另外一篇文章)

______________________________________________________

請尊重勞動成果,轉帖請附上 博客園 tony_lp 首發

相關文章
相關標籤/搜索