Log4cpp
是C++開源日誌庫,爲 C++ 應用程序開發中提供了日誌的追蹤和調試功能,基於 LGPL
開源協議,移植自 java 的日誌項目 log4j, 並在 api 上保持了一致性。java
1. 環境
- windows 7 64b + Qt5.7 + MinGW530
- log4cpp: 1.1.3
2. 下載
3.特色
- 可擴展,提供了多種記錄方式:文件、命令行、內存、win事件日誌…
- 能夠動態控制日誌級別,進行動態調整
- 多語言支持,C(log4c), C++(log4cpp/log4cplus), java(log4j), python(log4p))
- 平臺無關性,源碼編譯後能夠運行在各大主流操做系統上
4. 編譯
打開工程後,能夠發現包含了多個工程編譯項目,不過基本都是基於VS的項目,不是我想要的,須要手動轉化成 Qt 項目,也就是編程 pro
形式。python
拷貝源碼目錄下的 include
和 Src
文件夾到本身新建的工程中,主要使用這兩部分,其他的先無論。編程
編寫 pro 文件windows
QT = core TEMPLATE = lib TARGET = log4cpp INCLUDEPATH += $$PWD/.. \ $$PWD/../../boost/ \ DEPENDPATH += $$PWD/.. DEFINES += LOG4CPP_HAVE_BOOST SOURCES += \ Appender.cpp \ AppenderSkeleton.cpp \ AppendersFactory.cpp \ ...... HEADERS += \ win32:{ LIBS += -L -lwsock32 -lws2_32 }
上述引入了 `boost 庫路徑,並添加了wsock32庫!不然編譯會出現錯誤。api
編譯成功後會生成對應的庫文件(靜態庫只有629KB):服務器
5. 使用
5.1 基本概念
- Catgory (種類)
- Appender (附加目的地)
- Layout (佈局)
- Priority (優先級)
- DNC (嵌套的診斷上下文)
5.1.1 Category
Category
級別,優先級能夠用來控制日誌輸出的數量,好比配置級別是 DEBUG ,則任意 log均可以被打印出來,若是配置級別是 ERROR,則只有高於這個級別的才能輸出.app
Category
真正完成了日誌記錄功能.socket
優先級: DEBUG < INFO < WARN < ERROR < FATAL函數
5.1.2 Appender
Appender
(輸出源) 負責將 layout 附加的消息 記錄到某個輸出設備上(好比:文件,socket).佈局
多個 Appender
能夠附加到一個 Category
上,這樣一個消息就能同時輸出到多個設備上
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 事件日誌
5.1.3 Layout
layout 類即佈局,其實就是用來控制日誌消息以怎麼樣的格式顯示(這些開源庫中類名比較怪,就不能直接點麼,不就是日誌格式麼,搞一個 layout )。主要有一下幾種格式:
-
log4cpp::BasicLayout
時間戳 + 優先級 + 類別 + NDC 標籤 + 日誌消息 -
log4cpp::PatternLayout
相似C語言中的 printf 格式化輸出,能夠指定格式輸出 -
log4cpp::SimpleLayout
優先級 + 日誌信息
以上日誌格式不太滿意,因此須要對其進行升級(自定義),沒有辦法,世上很難趕上本身滿意的東西,趕上喜歡的還要自定義。如下格式應該算是大部分人能接收到的格式:
[2017-12-03 15:10:50:393|ERROR : [fun: int main(int, char**)] [line:32] [time: "15:10:50.389" ] Msg: error test
通常的日誌消息須要包含時間戳,消息類型,以及打印該消息的具體文件中函數名稱、行數,消息內容。這樣的結構基本能夠知足平常開發需求。
繼承關係:
5.1.4 Priority
優先級在 Category中描述過.
5.1.5 DNC
暫時不瞭解
5.2 配置文件
使用 log4cpp 有兩種方式,一種是本身手動編寫配置步驟,比較繁瑣,另外一種是直接經過配置文件便可完成.
5.3 使用
因爲 log4cpp 類名較長,操做不便,因此進行二次分裝比較方便
- 讀取配置文件
- 實例化 category對象
- 封裝日誌輸出方法
5.3.1 讀取配置文件
bool Log4CppUtility::loadConfigFile(QString strConfigFile, QString strParentPath) { try { QByteArray dataConfigFile = strConfigFile.toLocal8Bit (); QByteArray dataParentPath = strParentPath.toLocal8Bit (); log4cpp::PropertyConfigurator::configureEx ( dataConfigFile.data (), dataParentPath.data ()); } catch ( log4cpp::ConfigureFailure & e) { log4cpp::Category::getRoot ().warn (e.what ()); // qDebug()<<"configureEx problem:"<<e.what (); return false; } return true; }
5.3.2 實例化Category
bool Log4CppUtility::outputLog(xx,xxx,xxx,...) { log4cpp::Category & category = strCategoryName.isEmpty ()? log4cpp::Category::getRoot (): log4cpp::Category::getInstance ( strCategoryName.toStdString () ); //日誌等級區分 switch (Level) { case LP_EMERG: { category.emerg ( strMsg.toStdString () ); bOutputMsg = category.isEmergEnabled (); } break; case LP_ALERT: { category.alert ( strMsg.toStdString () ); bOutputMsg = category.isAlertEnabled (); } break; //其餘相似...... }
5.3.1 日誌輸出方法
編寫一個宏定義
#define LOGERROR(format, ...) Log4CppUtility::formateLog(__FILE__, __PRETTY_FUNCTION__, __LINE__, CATEGORYNAME, Log4CppUtility::LP_ERROR, format, ##__VA_ARGS__); //其餘相似...
調用:
#include <QDebug> #include <QCoreApplication> #include "loginclib.h" #include <QThread> class MyThread:public QThread { public: MyThread() { m_nCount = 10000; } ~MyThread(){} protected: virtual void run() { while (m_nCount) { LOGERROR("error:"+QString::number (m_nCount)); m_nCount--; msleep (4); } } private: int m_nCount; }; int main(int argc, char *argv[]) { QCoreApplication app(argc ,argv); qDebug()<<"=====start test log====="; QString strFilePath = QCoreApplication::applicationDirPath ()+"/"; QString logConfig = "LogProperty.conf"; logConfig = strFilePath + logConfig; if ( !Log4CppUtility::loadConfigFile ( logConfig )) { qDebug()<<"set path error!"; return 0; } MyThread thread; thread.start (); qDebug()<<"=====end test log====="; int ret = app.exec (); Log4CppUtility::shutDown (); return ret; }
新建一個線程不斷的輸出日誌到文件(這裏只顯示5條記錄).
使用是很方便的:
LOGERROR("this is error info");
實際結果:
http://kevinlq.com/2017/12/03/build_use_log4cpp/#2-下載