貓頭鷹的深夜翻譯:在JAVA中記錄日誌的十個小建議

前言

首先,這篇文章沒有進行任何的日誌功能的詳細介紹,而是對日誌提出了幾種最佳實踐。適合對日誌記錄有所瞭解的同窗閱讀。
下面是正文:java

JAVA日誌管理既是一門科學,又是一門藝術。科學的部分是指了解寫日誌的工具以及其API,而選擇日誌的格式,消息的格式,日誌記錄的內容,哪一種消息對應於哪種日誌級別,則徹底是基於經驗。從過去的實踐證實,JAVA的日誌記錄會嚴重的影響性能。我也曾屢次親眼見到在DEBUG模式下運行的在線股票交易程序,比在WARN或是其它更高層次模式下運行時延時要嚴重的多。延時和速度是任何電子交易平臺或是股票交易平臺的一個重大關注點,因此咱們必須瞭解並掌握JAVA日誌及其最佳實踐。這不只僅只是爲了用在金融或是投資銀行領域,它適用於全部既追求速度又須要日誌功能的應用。面試

爲什麼須要日誌

這是一個很基本的爭議,人們會爭辯說,咱們可使用System.out.println()來打印消息,爲什麼還須要日誌呢?每一個人剛開始接觸JAVA時,都使用System.out.println()在控制檯打印消息。可是它的功能遠遠沒有日誌記錄API如log4j或是java.util.logging強大。若是你正在寫一個java服務器應用,那麼你只有經過日誌文件才能知道你的服務器在作什麼。若是你沒有記錄任何日誌,那麼沒有人知道你的服務器在幹啥。而若是你的服務器做爲一箇中間件鏈接到應用中時,好比從股票交易系統或是電子交易系統得到輸入流,將其轉換並標準化後發送到輸出流,這時日誌就更爲重要。沒有日誌你根本不知道究竟哪裏出了問題。所以,日誌在JAVA中是必不可少的。數據庫

JAVA中有哪些不一樣的日誌級別

使用過JAVA日誌的童鞋必定知道這些基礎的日誌級別好比DEBUG, INFO, WARN和ERROR安全

DEBUG是最低的限制級別。這個級別只能用於開發和測試環境中,不能夠用於生產環境。服務器

INFO略高於DEBUG的限制級別,咱們應該用這個級別記錄一些信息型消息好比服務器啓動成功,輸入的數據,輸出的數據等等。微信

WARN的限制級別高於INFO,它用來記錄警告信息好比客戶端和服務器之間的鏈接中斷,數據庫鏈接丟失,Socket達到上限。這些信息是最爲重要的,由於你能夠在這些信息出現時發出警告,從而讓運維團隊管理應用程序的運行,並及時處理這些報錯。併發

ERRORWARN的限制級別還高,用於記錄ERRORException。你能夠在該日誌級別上設置警報裝置,而且提醒運維團隊對之作出處理。ERROR很是重要,你必須將其記錄下來。運維

FATAL是指可能致使程序終止的很是嚴重的時間。在這種事件以後你的應用極可能會崩潰。高併發

OFF具備最高的級別,旨在關閉JAVA中的日誌功能。工具

這些日誌級別是根據slf4j整理的,和java.util.loggingAPI中定義的級別不太同樣。java.util.logging還提供了其它的基於問題嚴重性進行劃分的日誌級別如SEVERE, FINER, FINEST, FATAL 等。

使用log4j仍是java.util.logging

clipboard.png

我會推薦使用log4j,你可能會對此持有異議。我也贊成java.util.logging的功能很強大,可是我發現log4j更易於使用。你已經瞭解了log4j的各個日誌級別,這裏每一個級別都很是恰當的描述了其功能。log4j還提供了額外的靈活性,你無需從新啓動應用來改變日誌的級別。固然,你也能夠在java.util.logging中經過JMX實現這個功能。

log4j還容許咱們在配置文件log4j.xml中設置每一個類的日誌級別。你既可使用XML文件也可使用properties文件進行配置。並且log4j是線程安全的。它被設計用於高併發的系統中。在另外一方面,我發現java.util.logging中的FormatterAppender功能很是棒。

爲什麼在JAVA中使用日誌會影響性能

一般來講,記錄日誌越頻繁,所需的IO操做就越多,從而影響了應用的性能。所以爲每個消息選擇一個合適的日誌級別是很是重要的。既然咱們不能不使用JAVA日誌,那麼咱們只能控制日誌的級別以及在那個級別上記錄的日誌內容。因此,必定要在isDebugEnabled()代碼塊中記錄DEBUG消息,以下所示:

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

在生產環境中必定要使用WARN或是更高級別的日誌記錄等級,必定不要使用DEBUG。它極可能成爲性能降低的罪魁禍首。

JAVA日誌的10個小建議

1.將DEBUG日誌訪日isDebugEnabled代碼塊

它能顯著的減小由於字符串拼接而帶來的性能的影響。

2.謹慎的消息的等級

當你在編寫服務器端應用時,這一點顯得格外的重要,由於它是你觀察服務器運行狀況的惟一途徑。若是你記錄了太多的日誌,則會影響服務器的性能,可是若是你不記錄重要的信息如輸入數據和輸出數據,那麼就很難識別究竟發生了什麼問題。

3.使用slf4j或是java.util.loggin

我推薦slf4j由於它的靈活性很是高。它容許在不重啓應用的前提下更改日誌級別。你能夠經過log4j的看門狗來不停的尋找目錄中的log4j.xml配置文件,而且在找到後重置日誌配置。

4.log4j能夠爲不一樣的類配置不一樣的日誌級別

你能夠將一些類設置爲INFO級別,再將另外一些類設置爲WARN級別或是ERROR級別。

5.日誌的格式化

不要忘了記錄線程的名稱和完整的JAVA類名,由於若是有多個線程同時在執行這段代碼,你可能根本找不出事件序列。在我看來,這一條建議最爲重要

6.從日誌中生成報告

在記錄日誌時要保證一致性和信息性,從而能夠分析日誌。

7.使用前綴來講明哪一部分代碼在打印日誌

前綴是指如客戶端,數據庫或是Session等等。以後你可使用grep或是find來找到和這些關鍵字相關的日誌。我在進行了這種實踐後發現它很是有助於debug或是調查事件,尤爲是當日志文件很龐大的時候。你能夠將全部數據庫級別的日誌加上前綴DB_LOG,再將全部SESSION級別的日誌加上前綴SESSION_LOG

8.若是某個日誌沒有分配等級,則將其繼承最近級別的等級

這也是爲何咱們老是將日誌等級分配到根日誌上log4j.rootLogger=DEBUG.

9.沒有日誌和過分日誌都是很差的

緣由前面已經說明

10.自檢日誌並調整日誌

最好用英文記錄日誌,並且要有良好的可讀性,從而在查閱時可以快速理解日誌。

11.使用標準化格式而不要自行拼接

logger.debug("No of Orders " + noOfOrder + " for client: " + client);//很差
logger.debug("No of Orders {} for client: {}", noOfOrder, client);

補充:記錄哪些信息以及各個信息對應什麼級別的日誌

1.不要記錄敏感信息

不要記錄敏感信息如密碼,身份證號,信用卡號或帳戶號。

2.儘可能記錄決策性信息

好比,一個JAVA應用須要從偏好文件或是環境中加載配置,若是沒有找到就使用默認的配置。若是你在使用默認配置,那麼你應當記錄以下信息:

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

這個日誌丟失了一個關鍵性信息,爲何沒法加載到我的配置?所以若是出現異常的話,還應當記錄異常。固然,這條日誌也提供了有用的信息,好比到底是哪一個用戶遇到了這個問題。

3.一致性

一致性在日誌和編碼中都很重要。不管你採用哪一種格式,你都應當堅持一致性。你應當花些時間仔細考慮日誌的格式,從而用它來捕獲有用的信息。

4.記錄一切出現問題時輔助debug的信息

舉個例子,咱們常常在應用中將String轉化爲Date,若是String的格式不正確的話,咱們一般會拋出ParseException。可是我常常看到有的代碼裏捕獲了這個異常以後,將Date賦值爲null並打印以下日誌:

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

看到這行日誌的時候,你根本不知道那個date傳入了不合法的值。它也沒有打印出不合法的String的內容到底是什麼。你須要這些信息來解決這個問題。一個更好的日誌信息以下:

logger.info("invalid startDate: {}", startDate);

clipboard.png
想要了解更多開發技術,面試教程以及互聯網公司內推,歡迎關注個人微信公衆號!將會不按期的發放福利哦~

相關文章
相關標籤/搜索