1. 程式人生 > >流行的開源日誌庫對比

流行的開源日誌庫對比

前段時間的一個C#專案我用了log4net,感覺不錯。最近開了個新坑,對於伺服器來說,日誌是必不可少的元件,當然不僅僅是服務端程式,在大多數客戶端程式上也需要用日誌來記錄使用者的一些行為以及操作過程。除了為.net準備的log4net之外,類似的開源日誌庫其實還有log4j, log4cxx, log4cpp,log4cplus, glog等,還有為C語言準備的log4c,為python準備的log4p,以及最原始的log4j。對於C++系列的幾個,估計有人會困擾應該選哪個,因此我在這裡做一個歸納:

  • log4cxx:Apache的產品,屬於apache的子專案之一,由log4j移植過來的。移植過來的東西多數都有一個特點,那就是要依賴各種碗糕。log4cxx就需要依賴apr-utils,編譯起來沒那麼直接,因此我放棄了它。
  • log4cpp:感覺上log4cpp和log4cplus大同小異,支援的功能也類似。上上一次更新是在2007年,不過在時隔五年之後的去年年底(2012年),它突然又更新了, 從1.0版提升到了1.1版,有點不容易,感覺詐屍了。另外,它也是由log4j移植過來的。
  • log4cplus:log4cplus究竟和log4cpp區別在哪,如果一定要作對比似乎log4cplus比log4cpp複雜了那麼一點點。log4cplus的功能比log4cpp支援的功能更加全面,支援執行緒安全(log4cpp的程式碼裡也做了一些對執行緒安全的保證,但官方沒有介紹它支援執行緒安全,反而log4cplus宣稱自己是執行緒安全的)
    ,另外log4plus更新非常頻繁,對於一個有版本潔癖的人來說,這也是我選擇它的原因,新版本提供了vc10的解決方案,還支援可選編譯Unicode和非Unicode版本。
  • glog:這個就不介紹了,全稱Google Glog, Google的東西一直比較讓人放心。它比log4系列的庫都要簡單,不過它不支援用配置檔案控制日誌行為,這對我來說是個遺憾。

log4系列的庫前身都是log4j,log4j真是深藏功與名。以下通過log4plus來介紹一下它的基本用法和魅力。

log4plus基本用法

log4cplus用了properties配置檔案對日誌行為進行配置,從java移植過來的東西,用properties檔案作為配置不奇怪。它的格式基本上是key=value,一項佔一行,以#號作為註釋的開始。

我的新坑專案有客戶端和服務端,當我們想為兩邊配置不同的日誌輸出格式時,就需要用到了log4plus提供的appender概念。在定義appender之前,需要先為client和server配置logger物件。完整的配置如下:

log4cplus.logger.SERVER_LOGGER=DEBUG, ServerAppender
log4cplus.logger.CLIENT_LOGGER=DEBUG, ClientAppender

#server appender configuration
log4cplus.appender.ServerAppender=log4cplus::ConsoleAppender
log4cplus.appender.ServerAppender.layout=log4cplus::PatternLayout
log4cplus.appender.ServerAppender.layout.ConversionPattern=%d[%m/%d/%y %H:%M:%S] [%t] %-5p %c - %m %n

#client appender configuration
log4cplus.appender.ClientAppender=log4cplus::ConsoleAppender
log4cplus.appender.ClientAppender.layout=log4cplus::PatternLayout
log4cplus.appender.ClientAppender.layout.ConversionPattern=%d[%m/%d/%y %H:%M:%S] [%t] %-5p %c - %m %n

前面兩行是定義了兩個Logger物件,物件名分別是SERVER_LOG和CLIENT_LOGGER。在編寫程式的時候,可以通過getInstance方法來取得Logger物件。右邊的是Logger物件的值,DEBUG表示日誌的級別,而用逗號隔開的右邊的是與改Logger物件繫結的Appender。定義Logger物件的格式如下:

log4cplus.logger.LoggerName=LogLevel, AppenderName

接下來的內容就是定義Appender,所謂的appender其實是用於定義日誌的輸出媒介與各種引數。其中log4cplus::ConsoleAppender定義了由控制檯輸出。layout物件用於描述Appender的輸出格式,而Appender就是輸出型別。log4plus支援多種輸出渠道,而且可以同時在配置中定義,比如:通過控制檯,日誌檔案,VC的DEBUG視窗,網路(SOCKET)等方式。此處以控制檯為例。定義格式如下:

log4cplus.appender.AppenderName=log4cplus::ConsoleAppender
log4cplus.appender.AppenderName.layout=log4cplus::PatternLayout
log4cplus.appender.AppenderName.layout.ConversionPattern=%pattern

這裡要注意的是,不同的Appender有不同的layout引數可配置,比如說如果你用了檔案輸出方式的Appender(FileAppender / RollingFileAppender / DailyRollingFileAppender),那麼就會有filename等類似配置項。

寫完配置檔案,那就應該在程式碼中把它搞起來。log4plus提供了一些很簡單的呼叫方法,程式碼如下:

1 2 3 4 5 6 7 8 log4cplus::initialize(); PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("log4cplus.properties.conf")); Logger serverLogger = Logger::getInstance(LOG4CPLUS_TEXT("SERVER_LOG")); Logger clientLogger = Logger::getInstance(LOG4CPLUS_TEXT("CLIENT_LOG")); LOG4CPLUS_DEBUG(serverLogger,"server log"); LOG4CPLUS_DEBUG(clientLogger , "client log");

程式碼很容易理解:
log4cplus::initialize()
初始化log4cplus環境,在初始化的時候呼叫一次即可。
PropertyConfigurator::doConfigure()
載入配置檔案,也是呼叫一次即可。這裡要注意根據你的是否是Unicode版本而使用LOG4CPLUS_TEXT巨集。
Logger::getInstance()
獲取一個Logger物件,該物件在配置中定義。唯一引數就是Logger物件的名稱。獲取成功的話會返回一個Logger類的例項。
LOG4CPLUS_DEBUG()
是個巨集,根據所獲得的Logger物件輸出一行DEBUG日誌,類似的還有LOG4CPLUS_INFO, LOG4CPLUS_WARN, LOG4CPLUS_ERROR等。

附錄

一、日誌內容轉義符(Pattern)

(1)”%%”,轉義為% 。
(2)”%c”,輸出logger名稱,如test.subtest 。也可以控制logger名稱的顯示層次,比如”%c{1}”時輸出”test”,其中數字表示層次。
(3)”%D”,顯示本地時間,比如:”2004-10-16 18:55:45″,%d顯示標準時間。
可以通過%d{…}定義更詳細的顯示格式,比如%d{%H:%M:%s}表示要顯示小時:分鐘:秒。大括號中可顯示的預定義識別符號如下:
%a — 表示禮拜幾,英文縮寫形式,比如”Fri”
%A — 表示禮拜幾,比如”Friday”
%b — 表示幾月份,英文縮寫形式,比如”Oct”
%B — 表示幾月份,”October”
%c — 標準的日期+時間格式,如 “Sat Oct 16 18:56:19 2004″
%d — 表示今天是這個月的幾號(1-31)”16″
%H — 表示當前時刻是幾時(0-23),如 “18″
%I — 表示當前時刻是幾時(1-12),如 “6″
%j — 表示今天是哪一天(1-366),如 “290″
%m — 表示本月是哪一月(1-12),如 “10″
%M — 表示當前時刻是哪一分鐘(0-59),如 “59″
%p — 表示現在是上午還是下午, AM or PM
%q — 表示當前時刻中毫秒部分(0-999),如 “237″
%Q — 表示當前時刻中帶小數的毫秒部分(0-999.999),如 “430.732″
%S — 表示當前時刻的多少秒(0-59),如 “32″
%U — 表示本週是今年的第幾個禮拜,以週日為第一天開始計算(0-53),如 “41″
%w — 表示禮拜幾,(0-6, 禮拜天為0),如 “6″
%W — 表示本週是今年的第幾個禮拜,以週一為第一天開始計算(0-53),如 “41″
%x — 標準的日期格式,如 “10/16/04″
%X — 標準的時間格式,如 “19:02:34″
%y — 兩位數的年份(0-99),如 “04″
%Y — 四位數的年份,如 “2004″
%Z — 時區名,比如 “GMT”
(4)”%F”,輸出當前記錄器所在的檔名稱,比如”main.cpp”
(5)”%L”,輸出當前記錄器所在的檔案行號,比如”51″
(6)”%l”,輸出當前記錄器所在的檔名稱和行號,比如”main.cpp:51″
(7)”%m”,輸出原始資訊。
(8)”%n”,換行符。
(9)”%p”,輸出LogLevel,比如”DEBUG”
(10)”%t”,輸出記錄器所在的執行緒ID,比如 “1075298944″
(11)”%x”,巢狀診斷上下文NDC (nested diagnostic context) 輸出,從堆疊中彈出上下文資訊,NDC可以用對不同源的log資訊(同時地)交叉輸出進行區分。
(12)格式對齊,比如”%-10m”時表示左對齊,寬度是10,當然其它的控制字元也可以相同的方式來使用,比如”%-12d”,”%-5p”等等。

二、Appender型別

(1)控制檯輸出
ConsoleAppender
(2)檔案輸出
FileAppender / RollingFileAppender / DailyRollingFileAppender