01安裝配置與基本使用
一、介紹
Log4cpp是一個開源的C++類庫,它提供了在C++程式中使用日誌和跟蹤除錯的功能。使用log4cpp,可以很便利地將日誌或者跟蹤除錯資訊寫入字元流、記憶體字串佇列、檔案、回滾檔案、偵錯程式、Windows日誌、本地syslog和遠端syslog伺服器中。
Log4cpp有如下優點:
- 提供了可擴充套件的多種日誌記錄方式;
- 提供了NDC(巢狀診斷上下文),可用於多執行緒、多場景的跟蹤除錯;
- 提供了完整的日誌動態優先順序控制,可隨時調整需要記錄的日誌優先順序
- 可通過配置檔案完成所有配置並動態載入;
- 效能優秀,記憶體佔用小,經過編譯後的log4cpp.dll大小僅有160kb;
- 程式碼級的平臺無關性,Log4cpp原始碼經過編譯後,適用於大多數主流的作業系統和開發工具;
- 概念清晰,學習和使用方便,熟練程式設計師一天之內即可很好地應用log4cpp進行開發。
Log4cpp的主頁為:http://sourceforge.net/projects/log4cpp/
log4cpp是個基於LGPL的開源項⽬,移植⾃Java的⽇志處理跟蹤項⽬log4j,並保持了API上的⼀致。其類
似的⽀持庫還包括Java(log4j),C++(log4cpp、log4cplus),C(log4c),python(log4p)等。
二、安裝與編譯
這裡使用的是log4cpp-1.1.3
版本
#!/bin/bash tar zxf log4cpp-1.1.3.tar.gz cd log4cpp ./configure #其實也就是執行了一個shell指令碼 make make check sudo make install # 標頭檔案安裝路徑 /usr/local/include/log4cpp 庫安放位置 /usr/local/lib/ sudo ldconfig
三、使用細節
3.1 包含的內容物件
Log4cpp中最重要概念有Category(種類)、Appender(附加器)、Layout(佈局)、Priorty(優先
級)、NDC(巢狀的診斷上下⽂)。
Category、Appender與Layout三者的關係如下圖所示:
3.2 先舉個簡單的例子
#include "log4cpp/Category.hh" #include "log4cpp/FileAppender.hh" #include "log4cpp/BasicLayout.hh" int main(int argc, char *argv[]) { // 1. 例項化⼀個layout 物件 log4cpp::Layout *layout = new log4cpp::BasicLayout(); // 2. 初始化⼀個appender 物件 log4cpp::Appender *appender = new log4cpp::FileAppender("File Appender", "./01test.log"); // 3. 把layout物件附著在appender物件上 appender->setLayout(layout); // 4. 例項化⼀個category物件 log4cpp::Category &warn_log = log4cpp::Category::getInstance("zh_test"); // 5. 設定additivity為false,替換已有的appender warn_log.setAdditivity(false); // 5. 把appender物件附到category上 warn_log.setAppender(appender); // 6. 設定category的優先順序,低於此優先順序的⽇志不被記錄 warn_log.setPriority(log4cpp::Priority::WARN); // 記錄⼀些⽇志 warn_log.info("Program info which cannot be wirten"); warn_log.debug("This debug message will fail to write"); warn_log.alert("Alert info"); // 其他記錄⽇志⽅式 warn_log.log(log4cpp::Priority::WARN, "This will be a logged warning"); log4cpp::Priority::PriorityLevel priority; bool this_is_critical = true; if (this_is_critical) priority = log4cpp::Priority::CRIT; else priority = log4cpp::Priority::DEBUG; warn_log.log(priority, "Importance depends on context"); warn_log.critStream() << "This will show up << as " << 1 << " critical message"; // clean up and flush all appenders log4cpp::Category::shutdown(); return 0; } //編譯指令 // g++ -o 01test 01test.cpp -llog4cpp -lpthread
輸出:
3.3 從配置檔案的方式讀取日誌屬性使用
完整使用範例:
配置檔案:
#定義 root category 的屬性
log4cpp.rootCategory=WARN, console # console是appender物件
#定義 console 屬性
log4cpp.appender.console=ConsoleAppender # ConsoleAppender是控制檯型別
#log4cpp.appender.console.layout=PatternLayout # PatternLayout是模式樣式
#log4cpp.appender.console.layout.ConversionPattern=%d [%p] - %m%n # 格式
log4cpp.appender.console.layout=org.apache.log4cpp.BasicLayout
#定義 sample category 的屬性
log4cpp.category.sample=DEBUG, sample # sample是appender物件
#定義 sample appender 的屬性
log4cpp.appender.sample=FileAppender # 檔案型別
log4cpp.appender.sample.fileName=sample.log # 具體哪個log檔案
log4cpp.appender.sample.layout=PatternLayout
log4cpp.appender.sample.layout.ConversionPattern=%d [%p] - %m%n
# 設定sub1.sub2 的additivity屬性
log4cpp.additivity.sample.son=true
log4cpp.additivity.sample.daughter=true
#定義 sample.son category 的屬性
log4cpp.category.sample.son=DEBUG, son
#定義 son appender 的屬性
log4cpp.appender.son=FileAppender
log4cpp.appender.son.fileName=son.log
log4cpp.appender.son.layout=PatternLayout
log4cpp.appender.son.layout.ConversionPattern=%d [%p] - %m%n
#定義 sample.daughter category 的屬性
log4cpp.category.sample.daughter=DEBUG, daughter
#定義 daughter appender 的屬性
log4cpp.appender.daughter=FileAppender
log4cpp.appender.daughter.fileName=daughter.log
log4cpp.appender.daughter.layout=PatternLayout
log4cpp.appender.daughter.layout.ConversionPattern=%d [%p] - %m%n
測試程式:
// g++ -o 03test 03test.cpp -llog4cpp -lpthread
#include "log4cpp/Category.hh"
#include "log4cpp/PropertyConfigurator.hh"
#include "log4cpp/NDC.hh"
void test(log4cpp::Category& category)
{
log4cpp::NDC::push(__FUNCTION__); // 記錄NDC資訊
category.error("zhonghao");
log4cpp::NDC::pop();
}
int main(int argc, char* argv[])
{
log4cpp::PropertyConfigurator::configure("./03test_conf.conf");
log4cpp::Category& root = log4cpp::Category::getRoot();
log4cpp::Category& sample = log4cpp::Category::getInstance(std::string("sample"));
log4cpp::Category& sample_son = log4cpp::Category::getInstance(std::string("sample.son"));
log4cpp::Category& sample_daughter = log4cpp::Category::getInstance(std::string("sample.daughter"));
log4cpp::NDC::push(__FUNCTION__); // 記錄NDC資訊,容器中
test(root);
root.info("root.info()");
sample.info("sample.info()");
sample_son.info("sample_son.info()");
sample_daughter.info("sample_daughter.info()");
root.error("root.error()");
sample.error("sample.error()");
sample_son.error("sample_son.error()");
sample_daughter.error("sample_daughter.error()");
//其他輸出方式
sample_daughter.critStream() << "sample_daughter.critStream() << \" \" ";
sample_daughter << log4cpp::Priority::ERROR << "sample_daughter << log4cpp::Priority::ERROR << \" \";";
sample_daughter.log(log4cpp::Priority::WARN, "sample_daughter.log(log4cpp::Priority::WARN, \" \");");
// clean up and flush all appenders
log4cpp::Category::shutdown();
return 0;
}
四、⽇志級別
4.1 log 的優先順序
別解讀,參閱原始碼 log4cpp-1.1.3\include\log4cpp\Priority.hh
由⾼到低
EMERG
FATAL
ALERT
CRIT
ERROR
WARN
NOTICE
INFO
DEBUG
NOTSET
對應到 Category 相應函式,參閱原始碼 log4cpp-1.1.3\include\log4cpp\Category.hh
Category::emerg()
Category::fatal()
Category::alert()
Category::crit()
Category::error()
Category::warn()
Category::notice()
Category::info()
Category::debug()
以上函式都有 2 個過載函式,可分別接受格式化字串或 std::string,例如 debug(),有
void debug(const char* stringFormat, ...) throw();
void debug(const std::string& message) throw();
4.2 關於優先級別使⽤的建議:
開發運⾏時,設為 DEBUG 級,⽽正式運營時,則設為 NOTICE ;
⼀定要顯示出來的資訊則可以⽤ NOTICE 或以上級別;
跟蹤函式運⾏痕跡的資訊⽤ INFO 級別;
運⾏時除錯的資訊⽤ DEBUG 級別;