常用的 C++ 日誌框架
一、日誌框架
一個
經過專門設計
的實用程式,用於規範應用程式的日誌記錄過程,就是日誌框架。
日誌框架可以自己編寫(需要一定的能力哦),也可以由第三方(例如:log4cplus)提供。對於不同的日誌框架,各自在實現方式上也有所不同。
雖然可以簡單地“標準化”日誌(例如:呼叫檔案系統 API,將資訊寫入名為 log.txt 的檔案),但是要成為一個嚴格意義上的框架,必須要超越標準化。也就是說,
日誌框架必須通過處理日誌記錄來標準化解決方案,從而暴露一個標準的 API。
沒明白?那就再具體一些,設想一個日誌框架,封裝了三個主要部分:①日誌記錄 ②格式化 ③輸出地。
當想要捕獲程式的執行時資訊時,
首先要發出要記錄的資訊。然後格式化這些資訊,最後決定將它輸出到哪裡。
一般情況下,會輸出到檔案中,但是也可以將其輸出到控制檯、資料庫,或者任何能夠接收資料的地方。如果有一系列程式碼,能夠解決這些問題,那麼就可以被看作是一個日誌框架。
二、為什麼不是 cout
使用日誌,
只為成為更好的攻城獅。
也許有人會問:既然 C++ 中有 cout,為什麼還要使用日誌呢?
無法否認,在使用像 C++、Java、PHP 這樣的程式語言時,我們會經常將訊息列印到控制檯,因為這是開發、測試和除錯程式的一部分。但倘若我們正在處理一個服務端程式,卻無法看到其內部發生了什麼,這時該怎麼辦?唯一的可見性工具是日誌檔案,如果沒有日誌,我們就不能進行任何除錯,也無法知道程式內部在做什麼。
儘管 C++ 中有相當方便的 cout 輸出流,可以在控制檯上列印一些資訊,或者可以通過其他方式將這些資訊重定向到檔案中,但這對於實際的應用程式來說根本不夠。尤其對於複雜的 C++ 程式來說,像 log4cplus 或任何其他日誌框架能夠提供了更多的靈活性,而這是 cout 不可能完成的。
在編寫程式碼時,
使用日誌框架是一種很好的實踐。即使像《程式碼整潔之道》這樣的書籍,也建議學習像 Log4 這樣的框架進行日誌記錄。
所以,應儘可能的在生產程式碼中使用日誌,而不是用 cout 來列印東西(這是不可接受的)。三、使用日誌的好處
日誌是一個優秀系統不可或缺的組成部分。
對於很多人來說,日誌的作用僅限於除錯。其實不然,它在很多方面都非常有用。
日誌是最好的診斷工具
絕大多數人都曾面臨這樣的困境 - 一旦程式出現問題,很長時間都找不出原因!
缺少日誌,我們將不得不依賴於客戶或技術支援,讓他們描述在什麼情況下發生了什麼(很可能會存在一些誤導)。隨後我們需要通過開發環境重現問題,並進行各種除錯,直至錯誤修復為止,然而這一般會耗費很長時間。
但若有日誌的幫助,我們便能迅速擺脫這種困境,可以很快地發現異常,並快速定位、解決問題!
日誌讓我們有機會監測模組的瓶頸
隨著專案規模的增加,模組會越來越多,調優也變成了一場持久戰。
通過記錄某些操作所花費的時間,我們可以及時地檢測模組的瓶頸,並針對性地對一些耗時操作做出優化。
日誌有助於我們瞭解使用者的行為
為了提高產品質量,提供個性化服務,就必須瞭解使用者行為 - 他們做了什麼,想要什麼。
要搞清楚這些,當然要有資料,所以
需要採集和分析使用者的行為,而日誌無疑是最主要的資料來源。
要不要重新發明輪子
不要去重新發明輪子 - 《麥肯錫方法》
既然已經對日誌框架有了明確的瞭解,那麼應該使用現有的日誌框架,還是構建自己的日誌框架呢?其實,這是一個老生常談的問題了 - 要不要重新發明輪子?引用莎士比亞戲劇《哈姆雷特》中的一句名言:
To be or not to be - that is the question.
現在我們正處於技術大爆發的時代,每一個技術領域中都有很多優秀的解決方案。因此,自己完全不需要、也不應該去寫日誌框架。就像不應該寫版本控制工具或 Bug 跟蹤管理工具一樣,其他人已經把這些東西搞出來了,而且搞的很好,Git、SVN,Bugzilla、Trac ...... 應有盡有,我們完全可以花很少的錢,甚至是免費使用它們。
所以,
請避免重複勞動,不要去重新發明輪子。應該堅持在自己的領域解決問題,將時間花在刀刃上。
話雖如此,但我們還是需要了解關於輪子的一些細節(誰造的?怎麼創造的?如何使用?),以從中接受靈感,並把自己的知識加進去。因此,當需要一個日誌框架時,應該使用現有的框架,而不是去重新發明輪子。那麼,問題來了,日誌框架都有哪些呢?
四、日誌框架都有哪些
C++ 中的日誌框架有很多,其中比較著名的有:
-
log4cxx:Java 社群著名的 Log4j 的 C++ 移植版,用於為 C++ 程式提供日誌功能,以便開發者對目標程式進行除錯和審計。
-
log4cplus:一個簡單易用的 C++ 日誌記錄 API,它提供了對日誌管理和配置的執行緒安全、靈活和任意粒度控制(也基於 Log4j)。
-
Log4cpp:一個 C++ 類庫,可以靈活地記錄到檔案、syslog、IDSA 和其他目的地(也基於 Log4j)。
-
google-glog:一個 C++ 語言的應用級日誌記錄框架,提供了 C++ 風格的流操作和各種輔助巨集。
-
Pantheios:一個型別安全、高效、泛型和可擴充套件性的 C++ 日誌 API 庫(號稱 C++ 領域速度最快的日誌庫)。
-
POCO:還提供了一個 好的日誌支援文件。
-
ACE:ACE 也有日誌支援。
-
Boost.Log:設計的非常模組化,並且可擴充套件。
-
Easylogging++:輕量級高效能 C++ 日誌庫(只有一個標頭檔案)。
-
G3log:一個開源、支援跨平臺的非同步 C++ 日誌框架,支援自定義日誌格式。基於 g2log 構建,提升了效能,支援自定義格式。
-
Plog:可移植、簡單和可擴充套件的 C++ 日誌庫。
-
spdlog:一個快速的 C++ 日誌庫,只包含標頭檔案,相容 C++11。
-
……
這麼多框架,應該選擇哪一個呢?
由於每個人的需求和技術棧都不一樣,所以很難直接回答這個問題,但是有一些選擇標準可供參考。
五、日誌選擇標準
易用性
易於使用的框架,
能讓你事半功倍。
易用性,是優秀框架的一個重要特性。所以無論使用什麼框架,都應優先考慮這一點。
對於日誌框架而言,一旦被選定,在後期開發過程中,專案組中的每個人都會頻繁使用。如果易用性不好的話,那絕對是一個噩夢!所以,在選擇日誌框架時,應儘量找那些由簡單、直觀的 API 實現的方案。衡量標準可參考:對於缺乏經驗的團隊成員,應該在檢視文件和簡單示例之後,就能夠快速上手。
效能(效率)
功能決定當下,效能決定未來。
另一個要考慮的重要因素是效能影響。正如上面提到的,我們會經常呼叫日誌,這可能會對程式的效能產生巨大的影響。
想象一下,一個日誌框架,需要花費很長的時間才能啟動,在每次呼叫時阻塞並執行檔案 I/O,缺少緩衝機制……對於這樣的框架,你會用嗎?
因此,在評估日誌框架時,可以參考網上的一些文章來比較,也可以自己做一些比較性實驗(基準測試),例如:吞吐量 - 測量每秒可以完成多少次方法呼叫(越高越好);取樣 - 測量每次呼叫執行究竟花費了多少時間(越低越好)。
對現有程式碼的影響
影響越小,越容易維護。
在以後的使用中,日誌將無處不在。就像會影響執行時效能一樣,它們也會影響原始碼的可維護性。從應用程式的角度來看,日誌所處的位置比較尷尬。之所以這麼說,是因為我們盡力隔離依賴性,提供良好的介面,並最小化耦合,在程式設計時考慮的是單一職責原則。然後日誌出現了,它到處都是,與周圍的程式碼無關。與這些優秀的設計原則相比,日誌顯得有些背道而馳。
因此,應充分考慮所引入日誌的影響範圍,儘量讓我們的程式碼改動最小化!
社群支援
每一個成功框架的背後,都有一個偉大的社群。
框架的生命力源於不斷地完善和發展,如果沒有強大的社群做支撐,這個框架便失去了源動力。
因此,在選擇框架時,這一點非常重要 - 所選的框架是否有專門的團隊做支撐?在像 Stack Overflow 這樣的問答網站上,它是否有很強的存在感?確保一點,如果在使用過程中遇到了問題,你能有辦法快速解決。倘若選擇了一個不知名的框架,當遇到了 Bug 時,那麼可能會浪費大量的時間來解決問題。
完整性
完整的框架,鑄就完美的生產力。
在最前面,我們將日誌的功能分為三個主要部分:日誌記錄、格式化和輸出地,所以要確保所選的日誌框架徹底解決了這些問題。
日誌記錄和輸出地比較基礎,幾乎所有日誌框架都有這些概念。話雖如此,但對於好的框架來說,應該巧妙地將日誌記錄與輸出地分開,並且還應該有多種可選的輸出地。在理想情況下,最好能夠自定義輸出地。
一般情況下,格式化日誌檔案會整齊地排列,並具有很好的可讀性。但在 DevOps 的世界裡,這些遠遠不夠。具體來說,日誌檔案需要被格式化為可解析的資料。通過將日誌輸出作為資料處理,可以很容易地聚合、搜尋和視覺化日誌,從而能夠在生產支援方面助你一臂之力。所以,要確保日誌框架擁有這種能力。
發展前景
只有前途光明,方能大行其道。
無法繞過這一點 - 在選擇日誌框架時,不僅要考慮它的現狀,還應該注重它的發展前景。
像上面提到的 C++ 日誌框架,每一個都非常優秀且特點鮮明。但有一些卻獲得了更多的關注度,例如 log4cplus、glog,為什麼如此呢?因為它們有很強大的“基因”和“後臺”,一個是著名的 Log4j 的衍生品,另一個則是 Google 的“親兒子”。
一個框架的發展前景,取決於眾多因素 - 關注度、使用者基數、社群活躍度 …… 要想大行其道,這些幾乎都不能少。