1. 程式人生 > >log4cpp 學習過程(一) 概述

log4cpp 學習過程(一) 概述

學習目的:通過學習開源框架,仔細研讀原始碼來提高C++的水平,並在最後通過Windows Linux平臺編譯和test來增加對兩個平臺的熟悉;

http://log4cpp.sourceforge.net/下載到log4cpp-1.0.tarlog4cpp-docs-1.0.tar,其實就是0.3.5版本;

下文引自:http://www.ibm.com/developerworks/cn/linux/l-log4cpp/index.html

log4cpp是個基於LGPL的開源專案,是基於優秀的日誌處理跟蹤專案Java語言的log4j移植過來的。log4j介紹的文件很多,在java領域使用的也比較廣泛,而這個功能強大的庫對國內的

C++語言開發人員卻使用的不多。

優點

提供應用程式執行上下文,方便跟蹤除錯;

可擴充套件的、多種方式記錄日誌,包括命令列、檔案、回捲檔案、記憶體、syslog伺服器、Win事件日誌等;

可以動態控制日誌記錄級別,在效率和功能中進行調整;

所有配置可以通過配置檔案進行動態調整;

多語言支援,包括Javalog4j),C++log4cpplog4cplus),Clog4c),pythonlog4p)等;

1. 原理

log4cpp3個主要的元件:categories(類別)、appenders(附加目的地)、和 layouts(佈局)。(為了方便大家理解,文中儘量使用英文原詞)

layout

類控制輸出日誌訊息的顯示樣式(看起來像什麼)。log4cpp當前提供以下layout格式:

log4cpp::BasicLayout // 時間戳優先順序(priority,下文介紹)

// 類別(category,下文介紹)

// NDC標籤(nested diagnostic contexts 下文介紹): 日誌資訊

// 如:1056638652 INFO main : This is some info

log4cpp::PatternLayout // 讓使用者根據類似於 C 語言 printf 函式的轉換模式來指定輸出格式。格式定義見程式碼附帶文件。

log4cpp::SimpleLayout //

優先順序(priority - 日誌資訊格式顯示。

appender類用來輸出日誌(被layout格式化後的)到一些裝置上。比如檔案、syslog服務、某個socket等。可以定義自己的appender類輸出日誌資訊到別的裝置上,比如應用自身的日子處理程序、資料庫等。appenderlayout的關係是layout附在appender上,appender類呼叫layout處理完日誌訊息後,記錄到某個裝置上。log4cpp當前提供以下appender

log4cpp::IdsaAppender // 傳送到IDS或者logger, 詳細見 http://jade.cs.uct.ac.za/idsa/

log4cpp::FileAppender // 輸出到檔案

log4cpp::RollingFileAppender // 輸出到回捲檔案,即當檔案到達某個大小後回捲

log4cpp::OstreamAppender // 輸出到一個ostream

log4cpp::RemoteSyslogAppender // 輸出到遠端syslog伺服器

log4cpp::StringQueueAppender // 記憶體佇列

log4cpp::SyslogAppender // 本地syslog

log4cpp::Win32DebugAppender // 傳送到預設系統偵錯程式

log4cpp::NTEventLogAppender // 傳送到win 事件日誌

category 類真正完成記錄日誌功能,兩個主要組成部分是appenderspriority(優先順序)。優先順序控制哪類日誌資訊可以被這個category記錄,當前優先順序分為:NOTSET, DEBUG, INFO, NOTICE, WARN, ERROR, CRIT, ALERT FATAL/EMERG 。每個日誌資訊有個優先順序,每個category有個優先順序,當訊息的優先順序大於等於category的優先順序時,這個訊息才會被category記錄,否則被忽略。優先順序的關係如下。category類和appender的關係是,多個appender附在category上,這樣一個日誌訊息可以同時輸出到多個裝置上。

NOTSET < DEBUG < INFO < NOTICE < WARN < ERROR < CRIT < ALERT < FATAL = EMERG

category被組織成一個樹,子category建立時優先順序預設NOTSETcategory預設會繼承父categoryappender。而如果不希望這種appender的繼承關係,log4cpp允許使用additivity 標籤,為false時新的appender取代categoryappender列表。

為了更好的理解上面的概念下面以手動使用方式舉例。

回頁首

2. 手動使用步驟

手動使用log4cpp的基本步驟如下:

例項化一個layout 物件;

初始化一個appender 物件;

layout物件附著在appender物件上;

呼叫log4cpp::Category::getInstance("name"). 例項化一個category物件;

appender物件附到category上(根據additivity的值取代其他appender或者附加在其他appender後)。

設定category的優先順序;

// FileName: test_log4cpp1.cpp

// Test log4cpp by manual operation.

// Announce: use as your own risk.

// Compile : g++ -otest1 -llog4cpp test_log4cpp1.cpp

// Run: ./test1

// Tested: RedHat 7.2 log4cpp0.3.4b

// Author: liqun ([email protected])

// Data: 2003-6-27

#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("FileAppender",

"./test_log4cpp1.log");

// 3. layout物件附著在appender物件上

appender->setLayout(layout);

// 4. 例項化一個category物件

log4cpp::Category& warn_log =

log4cpp::Category::getInstance("mywarn");

// 5. 設定additivityfalse,替換已有的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"

<< log4cpp::CategoryStream::ENDLINE;

// clean up and flush all appenders

log4cpp::Category::shutdown();

return 0;

}

回頁首

3. 配置檔案驅動方式使用步驟

另一個非常優秀的特徵就是通過讀取配置檔案,確定categoryappenderlayout等物件。也是我們非常推薦的使用方式,可以靈活地通過配置檔案定義所有地物件及其屬性,不用重新編碼,動態更改日誌記錄的策略。

Log4cpp主要提供了 log4cpp::PropertyConfigurator log4cpp::SimpleConfigurator兩種機制(檔案格式),但 log4cpp::SimpleConfigurator將來不再支援了,而且格式非常簡單,這裡就不多說明,自己看原始碼吧。

配置檔案的格式和log4j的配置檔案一樣,是標準的java屬性檔案格式。下面是附帶的例子配置檔案:

# a simple test config

#定義了3category sub1, sub2, sub1.sub2

log4j.rootCategory=DEBUG, rootAppender

log4j.category.sub1=,A1

log4j.category.sub2=INFO

log4j.category.sub1.sub2=ERROR, A2

# 設定sub1.sub2 additivity屬性

log4j.additivity.sub1.sub2=false

#定義rootAppender型別和layout屬性

log4j.appender.rootAppender=org.apache.log4j.ConsoleAppender

log4j.appender.rootAppender.layout=org.apache.log4j.BasicLayout

#定義A1的屬性

log4j.appender.A1=org.apache.log4j.FileAppender

log4j.appender.A1.fileName=A1.log

log4j.appender.A1.layout=org.apache.log4j.SimpleLayout

#定義A2的屬性

log4j.appender.A2=org.apache.log4j.ConsoleAppender

log4j.appender.A2.layout=org.apache.log4j.PatternLayout

log4j.appender.A2.layout.ConversionPattern=The message '%m' at time %d%n

配置檔案語法如下,不是很規範,結合上面的例子,應該可以看懂。

log4j / log4cpp . [category / appender].[category or appender 's name].[category or appender 's property]

= [Appender / Layout / property's value / Priority, appender name1 [appender name2 ...]]

[appender]

{ConsoleAppender}

{FileAppender}// appender的型別是FileAppender時,可以定義它下面的屬性。

[fileName]stringfoobar// 格式是:屬性名值的型別預設值

[append]booltrue

{RollingFileAppender}

[fileName] stringfoobar

[maxFileSize]num10*1024*1024

[maxBackupIndex]num1

[append]booltrue

{SyslogAppender}

[syslogName]stringsyslog

[syslogHost]stringlocalhost

[facility]num-1// * 8 to get LOG_KERN, etc. compatible values.

[portNumber]num-1

{IdsaAppender}

[idsaName]stringfoobar

{Win32DebugAppender}

{NTEventLogAppender}

[source]stringfoobar

[threshold]string ""// 全部

// 如果此型別appender需要layout,必須定義此appender<