摘要:是指可能導(dǎo)致程序終止的非常嚴(yán)重的時(shí)間。具有最高的級(jí)別,旨在關(guān)閉中的日志功能。因此為每一個(gè)消息選擇一個(gè)合適的日志級(jí)別是非常重要的。日志的個(gè)小建議將日志訪日代碼塊它能顯著的減少因?yàn)樽址唇佣鴰淼男阅艿挠绊憽?/p>
前言
首先,這篇文章沒有進(jìn)行任何的日志功能的詳細(xì)介紹,而是對(duì)日志提出了幾種最佳實(shí)踐。適合對(duì)日志記錄有所了解的同學(xué)閱讀。
下面是正文:
JAVA日志管理既是一門科學(xué),又是一門藝術(shù)??茖W(xué)的部分是指了解寫日志的工具以及其API,而選擇日志的格式,消息的格式,日志記錄的內(nèi)容,哪種消息對(duì)應(yīng)于哪一種日志級(jí)別,則完全是基于經(jīng)驗(yàn)。從過去的實(shí)踐證明,JAVA的日志記錄會(huì)嚴(yán)重的影響性能。我也曾多次親眼見到在DEBUG模式下運(yùn)行的在線股票交易程序,比在WARN或是其它更高層次模式下運(yùn)行時(shí)延時(shí)要嚴(yán)重的多。延時(shí)和速度是任何電子交易平臺(tái)或是股票交易平臺(tái)的一個(gè)重大關(guān)注點(diǎn),所以我們必須了解并掌握J(rèn)AVA日志及其最佳實(shí)踐。這不僅僅只是為了用在金融或是投資銀行領(lǐng)域,它適用于所有既追求速度又需要日志功能的應(yīng)用。
為何需要日志這是一個(gè)很基本的爭(zhēng)議,人們會(huì)爭(zhēng)辯說,我們可以使用System.out.println()來打印消息,為何還需要日志呢?每個(gè)人剛開始接觸JAVA時(shí),都使用System.out.println()在控制臺(tái)打印消息。但是它的功能遠(yuǎn)遠(yuǎn)沒有日志記錄API如log4j或是java.util.logging強(qiáng)大。如果你正在寫一個(gè)java服務(wù)器應(yīng)用,那么你只有通過日志文件才能知道你的服務(wù)器在做什么。如果你沒有記錄任何日志,那么沒有人知道你的服務(wù)器在干啥。而如果你的服務(wù)器作為一個(gè)中間件連接到應(yīng)用中時(shí),比如從股票交易系統(tǒng)或是電子交易系統(tǒng)獲得輸入流,將其轉(zhuǎn)換并標(biāo)準(zhǔn)化后發(fā)送到輸出流,這時(shí)日志就更為重要。沒有日志你根本不知道究竟哪里出了問題。因此,日志在JAVA中是必不可少的。
JAVA中有哪些不同的日志級(jí)別使用過JAVA日志的童鞋一定知道這些基礎(chǔ)的日志級(jí)別比如DEBUG, INFO, WARN和ERROR。
DEBUG是最低的限制級(jí)別。這個(gè)級(jí)別只能用于開發(fā)和測(cè)試環(huán)境中,不可以用于生產(chǎn)環(huán)境。
INFO略高于DEBUG的限制級(jí)別,我們應(yīng)該用這個(gè)級(jí)別記錄一些信息型消息比如服務(wù)器啟動(dòng)成功,輸入的數(shù)據(jù),輸出的數(shù)據(jù)等等。
WARN的限制級(jí)別高于INFO,它用來記錄警告信息比如客戶端和服務(wù)器之間的連接中斷,數(shù)據(jù)庫(kù)連接丟失,Socket達(dá)到上限。這些信息是最為重要的,因?yàn)槟憧梢栽谶@些信息出現(xiàn)時(shí)發(fā)出警告,從而讓運(yùn)維團(tuán)隊(duì)管理應(yīng)用程序的運(yùn)行,并及時(shí)處理這些報(bào)錯(cuò)。
ERROR比WARN的限制級(jí)別還高,用于記錄ERROR和Exception。你可以在該日志級(jí)別上設(shè)置警報(bào)裝置,并且提醒運(yùn)維團(tuán)隊(duì)對(duì)之做出處理。ERROR非常重要,你必須將其記錄下來。
FATAL是指可能導(dǎo)致程序終止的非常嚴(yán)重的時(shí)間。在這種事件之后你的應(yīng)用很可能會(huì)崩潰。
OFF具有最高的級(jí)別,旨在關(guān)閉JAVA中的日志功能。
這些日志級(jí)別是根據(jù)slf4j整理的,和java.util.loggingAPI中定義的級(jí)別不太一樣。java.util.logging還提供了其它的基于問題嚴(yán)重性進(jìn)行劃分的日志級(jí)別如SEVERE, FINER, FINEST, FATAL 等。
使用log4j還是java.util.logging我會(huì)推薦使用log4j,你可能會(huì)對(duì)此持有異議。我也同意java.util.logging的功能很強(qiáng)大,但是我發(fā)現(xiàn)log4j更易于使用。你已經(jīng)了解了log4j的各個(gè)日志級(jí)別,這里每個(gè)級(jí)別都非常恰當(dāng)?shù)拿枋隽似涔δ堋og4j還提供了額外的靈活性,你無需重新啟動(dòng)應(yīng)用來改變?nèi)罩镜募?jí)別。當(dāng)然,你也可以在java.util.logging中通過JMX實(shí)現(xiàn)這個(gè)功能。
log4j還允許我們?cè)谂渲梦募?b>log4j.xml中設(shè)置每個(gè)類的日志級(jí)別。你既可以使用XML文件也可以使用properties文件進(jìn)行配置。而且log4j是線程安全的。它被設(shè)計(jì)用于高并發(fā)的系統(tǒng)中。在另一方面,我發(fā)現(xiàn)java.util.logging中的Formatter和Appender功能非常棒。
為何在JAVA中使用日志會(huì)影響性能通常來說,記錄日志越頻繁,所需的IO操作就越多,從而影響了應(yīng)用的性能。因此為每一個(gè)消息選擇一個(gè)合適的日志級(jí)別是非常重要的。既然我們不能不使用JAVA日志,那么我們只能控制日志的級(jí)別以及在那個(gè)級(jí)別上記錄的日志內(nèi)容。所以,一定要在isDebugEnabled()代碼塊中記錄DEBUG消息,如下所示:
if(logger.isDebugEnabled()){ logger.debug("java logging level is DEBUG Enabled") }
在生產(chǎn)環(huán)境中一定要使用WARN或是更高級(jí)別的日志記錄等級(jí),一定不要使用DEBUG。它很可能成為性能下降的罪魁禍?zhǔn)住?/p> JAVA日志的10個(gè)小建議 1.將DEBUG日志訪日isDebugEnabled代碼塊
它能顯著的減少因?yàn)樽址唇佣鴰淼男阅艿挠绊憽?/p> 2.謹(jǐn)慎的消息的等級(jí)
當(dāng)你在編寫服務(wù)器端應(yīng)用時(shí),這一點(diǎn)顯得格外的重要,因?yàn)樗悄阌^察服務(wù)器運(yùn)行情況的唯一途徑。如果你記錄了太多的日志,則會(huì)影響服務(wù)器的性能,但是如果你不記錄重要的信息如輸入數(shù)據(jù)和輸出數(shù)據(jù),那么就很難識(shí)別究竟發(fā)生了什么問題。
3.使用slf4j或是java.util.loggin我推薦slf4j因?yàn)樗撵`活性非常高。它允許在不重啟應(yīng)用的前提下更改日志級(jí)別。你可以通過log4j的看門狗來不停的尋找目錄中的log4j.xml配置文件,并且在找到后重置日志配置。
4.log4j可以為不同的類配置不同的日志級(jí)別你可以將一些類設(shè)置為INFO級(jí)別,再將另一些類設(shè)置為WARN級(jí)別或是ERROR級(jí)別。
5.日志的格式化不要忘了記錄線程的名稱和完整的JAVA類名,因?yàn)槿绻卸鄠€(gè)線程同時(shí)在執(zhí)行這段代碼,你可能根本找不出事件序列。在我看來,這一條建議最為重要
6.從日志中生成報(bào)告在記錄日志時(shí)要保證一致性和信息性,從而可以分析日志。
7.使用前綴來說明哪一部分代碼在打印日志前綴是指如客戶端,數(shù)據(jù)庫(kù)或是Session等等。之后你可以使用grep或是find來找到和這些關(guān)鍵字相關(guān)的日志。我在進(jìn)行了這種實(shí)踐后發(fā)現(xiàn)它非常有助于debug或是調(diào)查事件,尤其是當(dāng)日志文件很龐大的時(shí)候。你可以將所有數(shù)據(jù)庫(kù)級(jí)別的日志加上前綴DB_LOG,再將所有SESSION級(jí)別的日志加上前綴SESSION_LOG
8.如果某個(gè)日志沒有分配等級(jí),則將其繼承最近級(jí)別的等級(jí)這也是為什么我們總是將日志等級(jí)分配到根日志上log4j.rootLogger=DEBUG.
9.沒有日志和過度日志都是不好的原因前面已經(jīng)說明
10.自檢日志并調(diào)整日志最好用英文記錄日志,而且要有良好的可讀性,從而在查閱時(shí)能夠快速理解日志。
11.使用標(biāo)準(zhǔn)化格式而不要自行拼接logger.debug("No of Orders " + noOfOrder + " for client: " + client);//不好 logger.debug("No of Orders {} for client: {}", noOfOrder, client);補(bǔ)充:記錄哪些信息以及各個(gè)信息對(duì)應(yīng)什么級(jí)別的日志 1.不要記錄敏感信息
不要記錄敏感信息如密碼,身份證號(hào),信用卡號(hào)或賬戶號(hào)。
2.盡量記錄決策性信息比如,一個(gè)JAVA應(yīng)用需要從偏好文件或是環(huán)境中加載配置,如果沒有找到就使用默認(rèn)的配置。如果你在使用默認(rèn)配置,那么你應(yīng)當(dāng)記錄如下信息:
logger.info("Not able to load personal settings, default Setting selected for user : {}", user);
這個(gè)日志丟失了一個(gè)關(guān)鍵性信息,為什么無法加載到個(gè)人配置?因此如果出現(xiàn)異常的話,還應(yīng)當(dāng)記錄異常。當(dāng)然,這條日志也提供了有用的信息,比如究竟是哪個(gè)用戶遇到了這個(gè)問題。
3.一致性一致性在日志和編碼中都很重要。無論你采用哪種格式,你都應(yīng)當(dāng)堅(jiān)持一致性。你應(yīng)當(dāng)花些時(shí)間仔細(xì)考慮日志的格式,從而用它來捕獲有用的信息。
4.記錄一切出現(xiàn)問題時(shí)輔助debug的信息舉個(gè)例子,我們經(jīng)常在應(yīng)用中將String轉(zhuǎn)化為Date,如果String的格式不正確的話,我們通常會(huì)拋出ParseException。但是我經(jīng)??吹接械拇a里捕獲了這個(gè)異常之后,將Date賦值為null并打印如下日志:
logger.info("failed to convert String to date")
看到這行日志的時(shí)候,你根本不知道那個(gè)date傳入了不合法的值。它也沒有打印出不合法的String的內(nèi)容究竟是什么。你需要這些信息來解決這個(gè)問題。一個(gè)更好的日志信息如下:
logger.info("invalid startDate: {}", startDate);
想要了解更多開發(fā)技術(shù),面試教程以及互聯(lián)網(wǎng)公司內(nèi)推,歡迎關(guān)注我的微信公眾號(hào)!將會(huì)不定期的發(fā)放福利哦~
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/68545.html
摘要:無需檢查的異常也是的子類。從低層拋出的需檢查異常強(qiáng)制要求調(diào)用方捕獲或是拋出該異常。當(dāng)前執(zhí)行的線程將會(huì)停止并報(bào)告該異常。單元測(cè)試允許我在使用中查看異常,并且作為一個(gè)可以被執(zhí)行的文檔來使用。不要捕獲最高層異常繼承的異常同樣是的子類。 前言 異常處理的問題之一是知道何時(shí)以及如何去使用它。我會(huì)討論一些異常處理的最佳實(shí)踐,也會(huì)總結(jié)最近在異常處理上的一些爭(zhēng)論。 作為程序員,我們想要寫高質(zhì)量的能夠解...
摘要:讀取出數(shù)據(jù)時(shí),將此版本號(hào)一同讀出,之后更新時(shí),對(duì)此版本號(hào)加一。此時(shí),將提交數(shù)據(jù)的版本數(shù)據(jù)與數(shù)據(jù)庫(kù)表對(duì)應(yīng)記錄的當(dāng)前版本信息進(jìn)行比對(duì),如果提交的數(shù)據(jù)版本號(hào)大于數(shù)據(jù)庫(kù)表當(dāng)前版本號(hào),則予以更新,否則認(rèn)為是過期數(shù)據(jù)。 前言 很多人都在討論數(shù)據(jù)的指數(shù)型增長(zhǎng),以及我們將會(huì)有比想象的還要大的數(shù)據(jù)量。但是,很少有人從數(shù)據(jù)庫(kù)的角度談?wù)撨@個(gè)問題。隨著數(shù)據(jù)量的暴漲,數(shù)據(jù)庫(kù)也需要隨之升級(jí)。這也是為什么既要了解如...
摘要:否則它就會(huì)用新的值替代當(dāng)前值。在這種情況下,鎖可能會(huì)優(yōu)于原子變量,但在實(shí)際的爭(zhēng)用級(jí)別中,原子變量的性能優(yōu)于鎖。在中引入了另外一個(gè)構(gòu)件。 題目要求 在我們深入了解CAS(Compare And Swap)策略以及它是如何在AtomicInteger這樣的原子構(gòu)造器中使用的,首先來看一下這段代碼: public class MyApp { private volatile int ...
摘要:因此,誤解幾乎是與之俱來的。這是完全錯(cuò)誤的。就像所強(qiáng)調(diào)的,對(duì)于一個(gè)被稱作的來說,狀態(tài)轉(zhuǎn)移管理是一個(gè)必須要完成的需求。你可以將其稱為或是,但是請(qǐng)不要把它叫做。 2000年的時(shí)候,Douglas Crockford聲明JavaScript是最被誤解的編程語言。這種誤解來源于不良的命名規(guī)范,錯(cuò)誤設(shè)計(jì),非標(biāo)準(zhǔn)模式等等。因此,誤解幾乎是與之俱來的。 我也在關(guān)于Restful架構(gòu)上發(fā)表了一個(gè)相似的...
閱讀 2099·2021-11-02 14:48
閱讀 2776·2019-08-30 14:19
閱讀 2942·2019-08-30 13:19
閱讀 1310·2019-08-29 16:17
閱讀 3246·2019-08-26 14:05
閱讀 3001·2019-08-26 13:58
閱讀 3088·2019-08-23 18:10
閱讀 1117·2019-08-23 18:04