C++之log4cpp庫的使用
1、Category,日誌輸出主體類,提供了輸出各種日誌級別的方法,並且能夠設置類別優先級,低於此優先級的類都不再輸出,可以有多個分類,但每個應用程序都有一個root分類,其他分類都是root分類的子分類,有點類似於java的單繼承結構,子分類的輸出同時會輸出到父分類中。
// 根分類root log4cpp::Category& root = log4cpp::Category::getRoot(); // 子分類subCat1 log4cpp::Category& sub1 = log4cpp::Category::getInstance("sub1"); root.error("test root error"); root.warn("test root error"); root.info("test root error"); sub1.fatal("test sub1 error"); sub1.notice("test sub1 error"); sub1.debug("test sub1 error");
2、Appender,主要是用來確定日誌輸出行為,例如輸出到哪兒,如何輸出。類Appender是由Category來加載的,一個Category可以加載多個Appender,輸出到多個地方,一個Appender也可以被多個Category加載,但是有些Appender類沒有設置互斥,日誌的多線程支持主要是在Category裏做的處理,因此不要使用一個Appender加載到多個Category中。
// OstreamAppender:輸出到輸出流中(輸出到控制臺上) // FileAppender:輸出到文件中 // RollingFileAppender:輸出到文件中並且能夠設置文件最大超過多少時生成新文件 // DailyRollingFileAppender:每天生成一個新文件 // NTEventLogAppender:將日誌輸出到Windows事件日誌中去 // ... log4cpp::Appender *appender = new log4cpp::FileAppender("test", "D:/log4cppTest/log4cppTest.log"); root.addAppender(appender);
3、Layout,設置日誌輸出風格,有BasicLayout、SimpleLayout、PatternLayout,其中BasicLayout,SimpleLayout主要是提供的成型的簡單日誌風格,實際中基本不會使用,主要是使用PatternLayout對日誌做格式輸出,Layout是加載到Appender中去的。
// %% 輸出一個% // %c 輸出Categroy名稱 // %d 輸出日期 // %m 輸出消息 // %n 輸出換行 // %p 輸出Priority // %d{%Y-%m-%d %H:%M:%S:%l}對輸出日期做定制,年月日時分秒毫秒 // %t 線程ID log4cpp::PatternLayout *patternLayout = new log4cpp::PatternLayout(); patternLayout->setConversionPattern("%d{%Y-%m-%d %H:%M:%S.%l} %t [%p] %m %n"); appender->setLayout(patternLayout);
4、Priority,log4cpp有如下幾級日誌級別
typedef enum { EMERG = 0, // emergency FATAL = 0, // fatal ALERT = 100, // alert CRIT = 200, // critical ERROR = 300, // error WARN = 400, // wanning NOTICE = 500, // notice INFO = 600, // infomation DEBUG = 700, // debug NOTSET = 800 } PriorityLevel;
其中每個Category都有一個level,低於此高於此level的日誌將不會輸出,比如Category設置priority為ERROR則,使用此Category輸出的WARN,NOTICE等級別的日誌都不會輸出, 當Category的Priority設置為NOTSET時,該Categroy繼承父Category的Priority;每個Appender也可以設置其threshold,當輸出日誌的Priority的值大於threshold時,此Appender將不會輸出此條日誌
// 代碼設置 root.setPriority(log4cpp::Priority::DEBUG); appender->setThreshold()
1、幫助類, log4cpp主要提供如下幾個類來簡化代碼設置:SimpleConfigurator,BasicConfigurator,PropertyConfigurator,其中SimpleConfigurator和BasicConfigurator,主要是使用代碼的方式,進行了一些簡單的默認配置,而PropertyConfigurator,是通過配置文件的方式對日誌進行配置,也是最常用的,下面就是配置文件的格式:
#文件名為logTest.Property #配置root Category的Priority為DEBUG, Appender為rootAppender log4cpp.rootCategory=DEBUG, rootAppender #配置子Category sub1的Priority為DEBUG, Appender為A1 log4cpp.category.sub1=DEBUG, A1 #配置rootAppender為FileAppender log4cpp.appender.rootAppender=FileAppender #配置日誌文件名為test1.log,存放在D盤根目錄下 log4cpp.appender.rootAppender.fileName=D:/test1.log #配置layout為PatternLayout log4cpp.appender.rootAppender.layout=PatternLayout #設置日誌輸出風格 log4cpp.appender.rootAppender.layout.ConversionPattern=%d{%Y-%m-%d %H:%M:%S.%l} %t [%p] %m %n #配置A1為RollingFileAppender log4cpp.appender.A1=RollingFileAppender #配置日誌文件名為test2.log,存放在D盤根目錄下 log4cpp.appender.A1.fileName=D:/test2.log #配置日誌文件最大不能超過1M log4cpp.appender.A1.maxFileSize=1024 * 1024 #日誌文件最多存儲3個文件,超過就會刪除舊的 log4cpp.appender.A1.maxBackupIndex=2 #設置日誌風格 log4cpp.appender.A1.layout=PatternLayout log4cpp.appender.A1.layout.ConversionPattern=%d{%Y-%m-%d %H:%M:%S.%l} %t [%p] %m %n // 代碼設置配置文件 log4cpp::PropertyConfigurator::configure(logTest.Property);
代碼使用
windows環境下
獲取到源代碼後,找到源碼目錄中的msvc10目錄,使用VS2010打開msvc10.sln解決方案文件,編譯源碼獲得log4cpp.DLL和log4cpp.lib;在源碼目錄中有include文件夾,將include整個拷貝到我們的工程目錄下,將include添加到工程屬性中的附加包含目錄中(QT工程則添加到INCLUDEPATH中去),這時就能夠正常使用了。
linux環境下
1.下載log4cpp-1.1.1.tar.gz
2. 安裝:先將log4cpp-1.1.1.tar.gz拖入用戶主目錄(~),
然後再執行以下步驟:
$ tar zxvf log4cpp-1.1.1.tar.gz
$ cd ~/log4cpp/
$ ./configure
$ make
$ make check
$ sudo make install
這裏已經安裝成功.
默認lib庫路徑是 : /usr/local/lib/
默認頭文件的位置: /usr/local/include/log4cpp
3. 使用:
3.1 編譯使用log4cpp庫的CPP文件時,要加上庫文件,才能順利的編譯通過,如下示例
$ g++ log4test.cpp -llog4cpp -lpthread
3.2 運行時,如若提示缺少log4cpp庫文件,表示找不到log4cpp的動態庫,需要進行以下設置
以管理員身份登錄終端,然後執行以下操作:
a. $ sudo vim /etc/ld.so.conf
b. 在打開的文件末尾另起一行添加動態庫log4cpp的路徑(這裏是/usr/local/lib),然後保存退出;
執行命令ldconfig使設置生效即可。
c. $ sudo ldconfig //更新庫文件的緩存信息
測試用例
#include <stdio.h> #include <time.h> #include <iostream> #include <boost/circular_buffer.hpp> #include <thread> #include <mutex> #include <vector> #include <stdio.h> #include <log4cpp/Category.hh> #include <log4cpp/FileAppender.hh> #include <log4cpp/SimpleLayout.hh> #include "log4cpp/PropertyConfigurator.hh" using namespace std; std::mutex g_mutex; // protects g_i // 1. circular_buffer 在多線程下是否需要加鎖 // ---- thread1 write // ---- thread2 read // ---- thread3 write boost::circular_buffer<int> cb(3); void thread1_foo() { int i = 0; while(i++ < 1000) { cb.push_back(i); { lock_guard<std::mutex> lock(g_mutex); cout << "thread1 write: " << i << endl; } } } void log_test() { try { log4cpp::PropertyConfigurator::configure("./log4cpp.conf"); } catch (log4cpp::ConfigureFailure& f) { std::cout << "Configure Problem " << f.what() << std::endl; } log4cpp::Category& root = log4cpp::Category::getRoot(); log4cpp::Category& sub3 = log4cpp::Category::getInstance(std::string("sub3")); for(int i = 0; i < 100; i++) { sub3.fatal("some test"); } } void thread2_foo() { int i = 0; while(i++ < 2000) { if(cb.empty()) { continue; } int a = cb[0]; cb.pop_front(); { lock_guard<std::mutex> lock(g_mutex); cout<< "thread2 read : "<< a << endl; } } } #define LOGFILE "./test.log" int main() { /*Setting up Appender, layout and Category*/ // log4cpp::Appender *appender = new log4cpp::FileAppender("FileAppender",LOGFILE);//第一個參數是appender的名字,第二個是log文件的名字 // log4cpp::Layout *layout = new log4cpp::SimpleLayout(); // //log4cpp::Layout *layout = new log4cpp::BasicLayout(); // log4cpp::Category& category = log4cpp::Category::getInstance("abc"); // // appender->setLayout(layout); // category.setAppender(appender); // category.setPriority(log4cpp::Priority::INFO); // // /*The actual logging*/ // category.info("This is for tracing the flow"); // category.notice("This is to notify certain events"); // category.warn("This is to generate certain warnings"); log_test(); return 0; }
g++ -std=c++11 -I/usr/local/include -I/users/jiangxf/3rdParty/boost -o log_test log_test.cpp liblog4cpp.a
# 定義了3個category sub1, sub2, sub3 # 其中sub2和sub3設置了additivity屬性為false;sub1的additivity屬性默認為true rootCategory=DEBUG, rootAppender category.sub1=,A1 category.sub2=INFO, A2 additivity.sub2=false category.sub3=ERROR, A3 additivity.sub3=false # 定義rootAppender類型和layout屬性,這裏使用了BasicLayout appender.rootAppender=org.apache.log4cpp.ConsoleAppender appender.rootAppender.layout=org.apache.log4cpp.BasicLayout #定義A1的屬性, 這裏使用了 SimpleLayout appender.A1=org.apache.log4cpp.FileAppender appender.A1.fileName=./log/A1.log appender.A1.layout=org.apache.log4cpp.SimpleLayout #定義A2的屬性,這裏使用了 PatternLayout appender.A2=org.apache.log4cpp.ConsoleAppender appender.A2.layout=org.apache.log4cpp.PatternLayout appender.A2.layout.ConversionPattern=The message ‘%m‘ at time %d%n #定義A3的屬性 #appender.A3=org.apache.log4cpp.RollingFileAppender appender.A3=org.apache.log4cpp.ConsoleAppender appender.A3.fileName=./log/A3.log appender.A3.maxFileSize=50 appender.A3.maxBackupIndex=3 appender.A3.backupPattern=%Y-%m-%d appender.A3.layout=org.apache.log4cpp.PatternLayout #appender.A3.layout.ConversionPattern=%d{%Y-%m-%d %H:%M:%S} [%p]: [%c] %m%n appender.A3.layout.ConversionPattern=%d,%p,%m%n #%c sub3 #%p fatal #%m 日誌內容 #%n 回車換行
log4cpp學習
http://blog.csdn.net/liuhong135541/article/category/1496383
C++之log4cpp庫的使用