1. 程式人生 > >聊聊日誌這件小事情

聊聊日誌這件小事情

聊聊日誌這件小事情

寫應用不寫日誌,只會在撞板後也不知道為何撞板。線上的問題永遠不會知道為何會發生,只會出現事故之後身處茫然之中。

1、哪怕用 print 也要輸出關鍵數據

新手會經常在調試的時候使用 print,不論這種方式的優劣,反正關鍵位置數據哪怕用 print 輸出都比沒有好。在 linux 系統,nohup 啟動進程的時候,可以把 print 輸出的內容導到一個文件。只要有 print,就多了一條路子來定位數據。

2、記錄日誌請用成熟的框架

真心不推薦用 print 來記錄日誌,為什麽呢?因為成熟的框架往往可以設置日誌的存儲方式和隨意控制存儲哪種級別日誌內容。

我們記錄日誌,大部分時候是不會翻閱的,但是我們很多時候又需要從日誌挖掘一些數據。例如每天請求某個接口多少次,然後有哪些接口請求耗時超過1秒的等諸如此類。

如果日誌需要用於分析,我們存在於文本,就需要編寫繁瑣的代碼來獲取結果。假如我們用了 mysql 或者 mongodb 等數據庫存儲日誌,我們就可以簡單調用API來統計數據。

我們再看看這些主流的日誌框架(例如 java 的 log4j,python 的標準庫 logging),他們往往提供若幹個記錄日誌的方法。例如 debug,info,warn,error 等。為什麽日誌要分等級呢?

當我們在開發過程中,我們往往想看每一個中間的運算過程的結果,但是在線上環境我們卻無需關註中間結果。如果我們有一個開關決定記錄哪種等級日誌,不是不用繁瑣修改代碼麽。

再者,各種等級日誌默認有一個標識字符串,方便我們隨時查閱各種級別的日誌,例如我們關註 error 而很多時候忽視 warning。

3、日誌分割

我們總不能把日誌只存儲在一個文件或者一個數據表裏面,一個原因是一些日誌時間久了就可以丟棄,以便節省存儲空間。另一個原因是,單文件單表在數據量不斷加大的情況下,查詢效率會不斷下降。

分割日誌,我們往往會采用兩種分割方法。

  • 按時間分割

  • 當數據量達到一定量的時候分割

當然,兩種方案都有自己的好處。不過個人比較推崇使用第一種分割方式,這種方法在統計的時候,處理難度相對較少。

4、我的日誌應該存放在哪裏?

讓我們來看看,一般日誌的存儲方式。

  • 文件

  • mysql

  • mongodb

  • hbase

  • PostgreSQL

除了上面那些存儲方案,還有很多,無法一一列出。

在應用的萌芽階段,用文件存儲日誌是利大於弊的。一者,使用簡單,無需復雜的配置,也無需額外的依賴。再者,一開始查錯都可以用 linux 的命令直接定位所需要的信息。

隨著應用的不斷發展,我們一個應用可能運行在多臺服務器上。如果我們依舊采用文件這種日誌存儲方案,我們想查閱日誌,還得一個一個服務器的找呢。這個時候,采用 mysql 這種存儲方案就很有必要性了。因為可以把日誌統一存在一個 mysql 數據庫裏面。

但是mysql沒法方便應對日誌數據項不斷變更的情況下,而 mongodb 由於是非關系型數據庫,數據結構可以隨時變動,並且寫效率比較高。

hbase在很多日誌分析框架中都作為存儲,應對海量數據還是不錯的,由於沒怎麽用過,就不好評論了。

5、我們需要一個統一的日誌平臺

當我們手頭有幾個應用在線上的時候,如果我們為每一個應用開一個數據庫來存儲,那麽還需要開若幹個日誌分析面板來翻閱日誌呢。

這個時候,我們需要一個統一的接口,一個平臺來管理所有應用的日誌。當然,我也自己造了一個輪子,代碼開源放在 https://github.com/yubang/ilog

6、實時日誌分析ELK平臺

這裏不是講解這套流行的日誌分析平臺的使用,而是看看它的工作原理。ELK其實是三個軟件,其中一個用於收集各臺服務器上的數據,然後一個是提供搜索分析服務的,一個就是可視化展示。

我們來看看收集日誌的東西:logstash,它是實時增量的把日誌同步到elasticsearch。對於收集日誌來說,難點就在增量和實時這兩個點。我所想到的方法是,記錄上一次讀取到的日誌行數,再次讀取用 seek 直接定位位置。實時可以監聽文件變化而觸發,系統有對應的API。

7、業務日誌

上面說的日誌都是用於線上發現BUG或者異常,用於系統分析。還有一類日誌,就是記錄一些特別的業務信息。例如一個用戶的余額系統,我們要記錄用戶什麽時候,在哪裏,用什麽途徑,充值了多少金額,充值前余額是多少,充值後余額是多少等。用戶在消費的時候同樣要記錄一堆信息。

8、日誌與代碼耦合問題

日誌的好處說了一大堆,但是當我們為應用添加日誌的時候,往往需要在代碼裏面添加一行又一行的代碼串。就像整潔光滑的墻壁,嵌入一顆一顆釘子,畫面沒有一絲違和感。

兩種可行的解決方案:

  • 使用鉤子函數

  • 無埋點日誌

使用鉤子函數很容易理解,以 flask 框架為例,可以掛載函數在一個請求前執行,也可以掛載函數在請求後執行。

無埋點日誌就比較復雜了,代碼不能直接寫在代碼裏面,那麽就是要在代碼運行的時候註入記錄日誌的代碼。一些現有的技術,例如百度統計的js,只需引入一個js就可以拿到一堆數據用於分析網站。


本文出自 “小菜鳥” 博客,轉載請與作者聯系!

聊聊日誌這件小事情