小白學習如何打日誌

前言

只有光頭才能變強。html

文本已收錄至個人GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3yjava

記得以前寫過一篇:《阿里巴巴 Java開發手冊》讀後感,以前自學時因爲沒怎麼接觸過打「日誌」,因此《手冊》中的「日誌規約」我就先放一邊去了。git

而以前寫了一篇:在公司作的項目和本身在學校作的有什麼區別?中就有提到:公司的項目不會有e.printStackTrace();這種代碼的存在。由於這打印出來的錯誤信息沒有日期、等級等等,分析起來不方便。github

在工做中去服務器上查日誌又是一個很是很是常見的操做,因此當初我又寫了一篇 工做中經常使用到的Linux命令,裏邊就談到了查日誌時經常使用的Linux命令。數據庫

想着,既然接觸日誌也有一段時間了,不妨在回看《手冊》,看看有什麼要注意的地方,因而就有了這篇筆記。服務器

1、Java打日誌的基礎

之前本身自學的時候,排查問題只會寫下面的代碼:框架

try {
   // doSomething
} catch (Exception e) {
    e.printStackTrace();
}
----------
// 查看某個數據的值時:
System.out.println(xxxx);

去到公司就發現上面的代碼全不見了,剩下的是:異步

LOGGER.info("begin to run Java3y:{}", id);
----
LOGGER.error("excepiton occurs when run Java3y {}, exception{}", id, e.toString());

若是使用e.printStackTrace();的話,打印在控制的信息分析不方便:性能

打印在控制的信息分析不方便

而咱們將信息分等級和時間記錄在服務器的磁盤上,有問題了就能夠根據對應的信息去查找相關的日誌(這樣排查起來是十分方便的):debug

服務器上的日誌信息

咱們再來看一下通常的日誌長什麼樣的:

日誌長的是什麼樣的

例如:如今有人來反饋某某某用戶好像收不到短信,給出發送時間和用戶ID,咱們就能夠在日誌上找出該用戶在咱們系統的發送狀態(例如圖上的:state:81,咱們就認爲是發送成功狀態)

那麼,問題來了,咱們在哪打日誌?《手冊》上其實已經給出了答案:

謹慎地記錄日誌。生產環境禁止輸出 debug 日誌;有選擇地輸出 info 日誌;若是使

用 warn 來記錄剛上線時的業務行爲信息,必定要注意日誌輸出量的問題,避免把服務器磁盤

撐爆,並記得及時刪除這些觀察日誌。

大量地輸出無效日誌,不利於系統性能提高,也不利於快速定位錯誤點。記錄日誌時請思考:這些

日誌真的有人看嗎?看到這條日誌你能作什麼?能不能給問題排查帶來好處?

1.1什麼叫作 打點 ?

打日誌最多見的就是用來打印出程序執行時的相關信息,用於快速定位問題和排查問題。我一開始也是這麼理解的,可是其實還能夠延伸一下。

我如今搞的那個系統,咱們還使用日誌在系統的執行鏈路上打點。好比說,我如今要推送一條通知消息,通知消息其實就是下面這種:

這就是通知消息

這個過程大概是如此的:

  • 首先別人調用個人RPC提供的接口(或者我本身調用本身的接口),發現這是一個通知消息。因而我組裝成對應的Task,異步放到消息隊列中
  • 另外一個系統從消息隊列中取出Task,對這個Task進行業務的處理(好比說是否夜間屏蔽,是否強制發送等等),而後調用HTTP接口把這個Task交給下游
  • 下游作的事其實也不少,整塊鏈路很長(好比要調用SDK的庫,Android和IOS又作不一樣的處理)

整塊鏈路

而咱們又但願在推送完了以後能統計出一些指標(曝光量,點擊率,轉化率)等等。因而乎,就須要在一些關鍵的位置上打一個日誌(專業點叫作打點

在整塊鏈路都打通了之後,將這些點位(日誌)收集起來,放到實時流式處理平臺(storm/flink)上清洗/過濾。若是是實時須要用到的放到Redis,離線的放在Hive。

2、手冊規範

2.1 使用門面模式的日誌框架

【強制】應用中不可直接使用日誌系統(Log4j、Logback)中的 API,而應依賴使用日誌框架

SLF4J 中的 API,使用門面模式的日誌框架,有利於維護和各個類的日誌處理方式統一

門面模式我以前也寫過一篇筆記:三分鐘學會門面模式!

其實說白了就是但願抽象出一層API,可以在切換具體日誌框架的時候不須要大面積更改

這個咱們能夠按學JDBC的時候去理解:

不管我是接入MySQL、Oracle仍是SQL Server,但個人接口永遠都是那一套,切換數據庫時不須要更改個人Java API

看了一下公司的項目,採用的是SLF4J+Logback

2.2 調用RPC接口使用Throwable類攔截

【強制】在調用 RPC、二方包、或動態生成類的相關方法時,捕捉異常必須使用 Throwable

類來進行攔截。

以前在排查問題的時候,有個問題死活排不出來,DeBug的時候一直沒進catch模塊。後來我學長就說:「要不你改爲Throwable試試?

try {

} catch (Throwable e) {
        
}

我就很疑問,說:「爲啥要改爲Throwable呢?咱們用Exception不就能夠捕獲全部的異常了麼,Exception是Throwable的一個子類,但Exception已是包含全部的Java異常了呀」

衆所周知,Throwable有兩個子類:

  • Error(通常咱們都會把這個忽略掉...通常狀況下出現了Error程序都運行不起來)
  • Exception
The  Throwable class is the superclass of all errors and exceptions in the Java language

在《手冊》上也有對上面的規則進行說明:

說明:經過反射機制來調用方法,若是找不到方法,拋出 NoSuchMethodException。什麼狀況會拋出

NoSuchMethodError 呢?二方包在類衝突時,仲裁機制可能致使引入非預期的版本使類的方法簽名不匹

配,或者在字節碼修改框架(好比:ASM)動態建立或修改類時,修改了相應的方法簽名。這些狀況,即

使代碼編譯期是正確的,但在代碼運行期時,會拋出 NoSuchMethodError

大概的意思就是說:調用 RPC、二方包、或動態生成類的相關方法時,可能直接拋出的是Error,而catch Exception是沒法捕得到到的。

想看例子的同窗能夠看看這篇文章:

最後

參考資料(阿里巴巴開發手冊下載地址):

查閱資料時發現的好文:

樂於輸出乾貨的Java技術公衆號:Java3y。公衆號內有200多篇原創技術文章、海量視頻資源、精美腦圖,關注便可獲取!

轉發到朋友圈是對我最大的支持!

以爲個人文章寫得不錯,點

相關文章
相關標籤/搜索