應用log4cxx在c++中記錄日誌
阿新 • • 發佈:2019-02-19
1.介紹
Log4cxx是開放原始碼專案Apache Logging Service的子專案之一,是Java社群著名的log4j的c++移植版,用於為C++程式提供日誌功能,以便開發者對目標程式進行除錯和審計。
有關log4cxx的更多資訊可以從Apache Loggin Service的網站http://logging.apache.org獲得。當前的穩定版本為0.9.7,本文內容及示例程式碼都是基於此版本。
請從官方網站獲得合適的版本。也可以從下面這個連結中直接獲取(直接的連結地址可能不會永遠有效):
下載完成後解壓縮到合適的目錄中
2.2編譯
原始發行包中不含編譯後的程式碼,這個工作需要我們自己來做。開啟你的IDE,開啟log4cxx.dsw,會載入以下目錄中的工程:
lMsvc\static:該工程產生log4cxx的靜態連結庫(lib4cxx.lib和lib4cxxs.lib);
lMsvc\dll:該工程產生log4cxx的動態連結庫(lib4cxx.dll)。
通常情況下,工程都可以順利編譯通過。檢視輸出目錄,把這些生成的庫檔案找出來,以便在下一步驟中使用。
請先在IDE中開啟一個需要加入日誌功能的工程,或者出於實驗目的,新建一個工程,以便對其進行設定。
首先需要設定log4cxx的include檔案。這些檔案位於log4cxx軟體包的include\log4cxx目錄內。請檢視你的VC++ IDE中“工具->選項->專案->VC++目錄->包含檔案”所列出的內容,以便確定你以何種方式加入這些include檔案:
l將include\log4cxx直接拷貝到已定義的包含檔案目錄中。如果將log4cxx看作是一項系統服務的話,這樣做是胡合乎情理的,因為你可以採用標準庫的方式使用它,例如:#include <log4cxx/logger.h>
l增加一個包含路徑,以指向位於IDE外部的某一檔案目錄。可以簡單的指向在2.1中解壓縮後形成的log4cxx軟體包目錄。
下一步需要對2.2節產生的log4cxx庫進行設定。這取決於你使用該庫的方式:靜態連結或者動態連結。
l靜態連結情況下需要做如下工作:為預編譯器定義LOG4CXX_STATIC巨集,設定位置為“Project->Setting->C/C++->Categroy->Preprossor->Proprossor Definitions”;為連結器指定依賴的庫lib4cxxs.lib和Ws2_32.lib
l動態連結情況下只需要為連結器指定依賴的庫lib4cxxs.lib即可,設定方式同上。
本節展示了一個最簡單的log4cxx示例,以便你可以快速的瞭解它。
該示例在功能上建立了一個日誌服務,該日誌可通過配置檔案進行必要控制,並可以同時向檔案和控制檯輸出資訊。
在實現上,我們採用了一個簡單的控制檯程式,並使用動態連結庫的方式使用log4cxx。
要實現這個目標,請按如下步驟進行:
1)建立一個名為logdemo的空白win32控制檯工程,並按照2.3節所述內容對其進行設定。注意,這裡我們使用動態連線口的方式。
2)在logdemo.cpp中加入實現日誌功能的程式碼。完成後的程式碼清單如下:
#include "stdafx.h"
#include <log4cxx/logger.h>
#include <log4cxx/propertyconfigurator.h>usingnamespace log4cxx;
int _tmain(int argc, _TCHAR* argv[])
{
//載入log4cxx的配置檔案,這裡使用了屬性檔案 PropertyConfigurator::configure("log4cxx.properties");
//獲得一個Logger,這裡使用了RootLogger LoggerPtr rootLogger = Logger::getRootLogger();
//發出INFO級別的輸出請求 LOG4CXX_INFO(rootLogger, _T("它的確工作了"));
//rootLogger->info(_T("它的確工作了")); //與上面那句話功能相當return0;
} ,因為我們在下一步中需要使用軟體包,包括編譯和複製必要的檔案。
# 設定root logger為DEBUG級別,使用了ca和fa兩個Appender
log4j.rootLogger=DEBUG, ca, fa
#對Appender fa進行設定:
# 這是一個檔案型別的Appender,
# 其輸出檔案(File)為./output.log,
# 輸出方式(Append)為覆蓋方式,
# 輸出格式(layout)為PatternLayout
log4j.appender.fa=org.apache.log4j.FileAppender
log4j.appender.fa.File=./output.log
log4j.appender.fa.Append=true
log4j.appender.fa.layout=org.apache.log4j.PatternLayout
log4j.appender.fa.layout.ConversionPattern=%d [%t] %-5p %.16c - %m%n
#對Appender ca進行設定:
# 這是一個控制檯型別的Appender
# 輸出格式(layout)為PatternLayout
log4j.appender.ca=org.apache.log4j.ConsoleAppender
log4j.appender.ca.layout=org.apache.log4j.PatternLayout
log4j.appender.ca.layout.ConversionPattern=%d [%t] %-5p %.16c - %m%n 4)複製log4cxx.dll到輸出目錄。在動態連結方式下,應用程式需要能夠找到這個庫檔案。 5)執行生成的logdemo.exe檔案,檢視一下執行結果,看看我們工作有沒有取得成效。如果一切順利,無論是在控制檯還是在輸出檔案中,都應該能看到類似下面那樣的輸出內容:
4.1核心類
Log4cxx有三個關鍵元件,它們是loggers, appenders和layouts。
Logger是log4cxx的核心類,只要執行日誌操作;looger有層次結構,最頂層為RootLogger;logger是有級別的。每個logger可以附加多個Appender。Appender代表了日誌輸出的目標,如輸出到檔案、控制檯等等。對於每一種appender,都可以通過layout進行格式設定。
這三類元件用示意圖表示如下(不代表類關係):
(TODO:在此對三種元件分別進行說明)
4.2配置類
此外在使用中還會用到的類有BasicConfigurator、PropertyConfigurator和DOMConfigurator等,用於對log4cxx進行配置。其中:
BasicConfigurator提供了一種簡單配置,包括使用ConsoleAppder作為root appender和PatternLayout作為預設佈局。
PropertyConfigurator使用properties檔案作為配置方式。
DOMConfigurator則使用properties檔案作為配置方式。
(TODO:在此對配置內容進行說明)
5.實踐指導
在專案中是否使用日誌,以及如何使用日誌,對開發者來說都是一個需要做出的技術選擇,這通常會牽扯到系統的效能,使用日誌的目的等問題。我們使用日誌的方式,有些是這個行業積累了多年的經驗,有些則純粹關乎個人的喜好。
1)何時使用日誌
通常情況下,日誌的作用在於除錯和審計,如果你的專案對此有特殊需求,即可考慮使用日誌。
對於除錯,通常用於IDE偵錯程式無法達到的地方。一些常見的場景包括:
分散式元件的除錯。在伺服器端的元件,需要通過客戶端的呼叫來驗證其工作是否正確,此時利用日誌的輸出作為輔助工具對錯誤進行診斷。
連結庫除錯。在無法跟蹤進外部庫中的情況下,這種方法非常有效。
生產環境下的除錯。生產環境通常是指產品在客戶處處於正式執行的狀態,在出現問題時,開發者常常不在現場,藉助日誌的輸出進行錯誤判斷就是一個非常有效的手段。
對於審計應用,則需要視特定的情況而定,程式級的記錄能力,無疑可以作為業務級審計手段的有效補充。
無論是在哪種場景下,log4cxx都是可以勝任工作的,這取決於它的靈活的配置能力及多種型別的輸出方式。
2)效能問題
關閉日誌,通過配置檔案設定日誌的關閉和開啟
使用巨集代替logger的輸出命令
選擇性輸出日誌。建立logger的層次結構,根據級別選擇性輸出
輸出目標。儘可能減少輸出目標
選擇合適的輸出格式。使用SimpleLayout將達到與std::cout相當的速度。
3)其它
使用類的全限定名對logger命名
6.結論
Log4cxx具有的一些顯著特性使得C++者可以將其放入自己的工具箱中,這些特性包括靈活的配置能力,多種輸出手段,豐富的格式控制,出色的效能。如果在你的開發中需要藉助於日誌進行除錯和審計,你也許需要log4cxx。最後,重要的一點是,如你所見,log4cxx的使用是如此的簡單。
如果在SDI或者MDI程式中,可以如下步驟使用log4cxxx:
1.在CXXXApp類的標頭檔案里加入以下幾行:
#include <log4cxx/logger.h>
#include <log4cxx/propertyconfigurator.h> using namespace log4cxx; 2.在CXXXApp類中增加public的成員變數:
LoggerPtr rootLogger; 3.在CXXXApp::InitInstance()的最底下增加如下程式碼:
PropertyConfigurator::configure("log4cxx.properties"); rootLogger = Logger::getRootLogger(); 4.以後就可以這樣輸入日誌記錄了:
((CXXXApp *)AfxGetApp())->rootLogger->info("On OA Manage!");
#include <log4cxx/logger.h>
#include <log4cxx/propertyconfigurator.h>usingnamespace log4cxx;
int _tmain(int argc, _TCHAR* argv[])
{
//載入log4cxx的配置檔案,這裡使用了屬性檔案 PropertyConfigurator::configure("log4cxx.properties");
//獲得一個Logger,這裡使用了RootLogger LoggerPtr rootLogger = Logger::getRootLogger();
//發出INFO級別的輸出請求 LOG4CXX_INFO(rootLogger, _T("它的確工作了"));
//rootLogger->info(_T("它的確工作了")); //與上面那句話功能相當return0;
} ,因為我們在下一步中需要使用軟體包,包括編譯和複製必要的檔案。
以Debug方式編譯工程,除錯程式直到成功為止。
3)新建一個文字檔案,命名為log4cxx.properties,並鍵入如下內容:# 設定root logger為DEBUG級別,使用了ca和fa兩個Appender
log4j.rootLogger=DEBUG, ca, fa
#對Appender fa進行設定:
# 這是一個檔案型別的Appender,
# 其輸出檔案(File)為./output.log,
# 輸出方式(Append)為覆蓋方式,
# 輸出格式(layout)為PatternLayout
log4j.appender.fa=org.apache.log4j.FileAppender
log4j.appender.fa.File=./output.log
log4j.appender.fa.Append=true
log4j.appender.fa.layout=org.apache.log4j.PatternLayout
log4j.appender.fa.layout.ConversionPattern=%d [%t] %-5p %.16c - %m%n
#對Appender ca進行設定:
# 這是一個控制檯型別的Appender
# 輸出格式(layout)為PatternLayout
log4j.appender.ca=org.apache.log4j.ConsoleAppender
log4j.appender.ca.layout=org.apache.log4j.PatternLayout
log4j.appender.ca.layout.ConversionPattern=%d [%t] %-5p %.16c - %m%n 4)複製log4cxx.dll到輸出目錄。在動態連結方式下,應用程式需要能夠找到這個庫檔案。 5)執行生成的logdemo.exe檔案,檢視一下執行結果,看看我們工作有沒有取得成效。如果一切順利,無論是在控制檯還是在輸出檔案中,都應該能看到類似下面那樣的輸出內容:
2006-06-02 16:09:50,609 [2528] INFO root - 它的確工作了 |
#include <log4cxx/propertyconfigurator.h> using namespace log4cxx; 2.在CXXXApp類中增加public的成員變數:
LoggerPtr rootLogger; 3.在CXXXApp::InitInstance()的最底下增加如下程式碼:
PropertyConfigurator::configure("log4cxx.properties"); rootLogger = Logger::getRootLogger(); 4.以後就可以這樣輸入日誌記錄了:
((CXXXApp *)AfxGetApp())->rootLogger->info("On OA Manage!");