Windows下MinGW跨平臺編譯和使用log4cpp

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-下載

相關文章
相關標籤/搜索