一塊兒學習log4cxx

目前成熟的日誌系統有不少,好比log4cxx,log4cpp等,今天一塊兒來學習log4cxx吧,之因此學習這個,首先,這個日誌庫比較成熟,一直由apach基金在維護,而log4cpp缺少維護.再者,這個庫的性能相對高一些,大約爲10w行/s.c++

log4cxx依賴於apach的另外兩個開源庫apr和apr-util.apache

準備工做:app

首先下載 apr-1.7.0.tar.gz, apr-util-1.6.1.tar.gzlog4cxx庫socket

百度網盤函數

提取碼: kzwc 性能

1. 安裝依賴庫apr和apr-util學習

#首先解壓壓縮包
$ tar -zxvf apr-1.7.0.tar.gz
$ cd apr-1.7.0

$ ./configure --prefix=/usr/local
$ make
$ sudo make install

 

#首先解壓壓縮包
$ tar -zxvf apr-util-1.6.1.tar.gz
$ cd apr-util-1.6.1

$ ./configure --prefix=/usr/local --with-apr=/usr/local
$ make
$ sudo make install

 

2.安裝log4cxx測試

tar -zxvf apache-log4cxx-0.10.0.tar.gz  
cd apache-log4cxx-0.10.0  
./configuer --prefix=/usr/local/ --with-apr=/usr/local/ --with-apr-util=/usr/local/  --with-charset=utf-8 --with-logchar=utf-8  
make
sudo make install

安裝log4cxx可能會報錯:ui

解決辦法:this

1 inputstreamreader.cpp:66: error: 'memmove' was not declared in this scope  
2 make[3]: *** [inputstreamreader.lo] 錯誤 1  
#這是因爲如下幾個文件缺乏了標準庫文件,添加上就能夠了
3 src/main/cpp/inputstreamreader.cpp添加#include <string.h>  
4 src/main/cpp/socketoutputstream.cpp添加#include <string.h>  
5 src/examples/cpp/console.cpp添加#include <string.h>;#include <stdio.h>;

3. 封裝log4cxx日誌庫
/*!
* Email: scictor@gmail.com
* Auth: scictor
* Date: 2019-9-8
* File: zlog4cxx.h
* Class: zlog4cxx (if applicable)
* Brief:
* Note:
 */

#ifndef ZLOG4CXX_H
#define ZLOG4CXX_H

#include <log4cxx/logger.h>
#include <log4cxx/logstring.h>
#include <log4cxx/propertyconfigurator.h>
#include<string>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace log4cxx;
using namespace log4cxx::helpers;
#include <stdarg.h>
using namespace std;
#define SAFE_DELETE_ARRAY(v_para)\
do \
{\
    if (NULL != v_para) {\
    delete[] v_para;\
    v_para = NULL;\
    }\
} while (0)
//TRACE < DEBUG < INFO < WARN < ERROR < FATAL
typedef enum _LOG_LEVEL
{
    LOG_TRACE_ = 0,
    LOG_DEBUG_,
    LOG_INFO_,
    LOG_WARN_,
    LOG_ERROR_,
    LOG_FATAL_
}LOG_LEVEL;
#ifndef IN
#define IN
#endif
#ifndef OUT
#define OUT
#endif
/*
寫日誌函數
IN const char* module,//在log4cxx.properties文件中設置了不少個append,這個參數用來設置模塊,例如本實例中的fa
IN const LOG_LEVEL level,日誌級別 ERROR、INFO等
IN const char* file,打印日誌函數調用的文件
IN const char* function, 打印日誌的函數
IN const int line, 打印日誌的行號
IN const char* format,//打印日誌的格式 如: "%s%d%f"
...                  //可變參數輸入
*/
void log4cxx_package(IN const char* module,IN const LOG_LEVEL level, IN const char* file, IN const char* function,
                     IN const int line, IN const char* format, ...);//
//宏定義封裝,__FILE__, __FUNCTION__, __LINE__ 分別是打印日誌的文件名、函數名,行號
#define LOG(module,level, format,...) log4cxx_package(module,level, __FILE__, __FUNCTION__, __LINE__, format,__VA_ARGS__)
//按照不一樣的級別定義宏
#define FIRE_ERROR(format,...) LOG("fa",LOG_ERROR_, format,__VA_ARGS__)
#define FIRE_INFO(format,...) LOG("fa",LOG_INFO_, format,__VA_ARGS__)
#define FIRE_TRACE(format,...) LOG("fa",LOG_TRACE_, format,__VA_ARGS__)
#define FIRE_DEBUG(format,...) LOG("fa",LOG_DEBUG_, format,__VA_ARGS__)
#define FIRE_WARN(format,...) LOG("fa",LOG_WARN_, format,__VA_ARGS__)
#define FIRE_FATAL(format,...) LOG("fa",LOG_FATAL_, format,__VA_ARGS__)   //
//初始化日誌庫,傳入log4cxx.properties文件的名稱
void log4cxx_init(IN const char* conffile);
//根據append或者模塊名稱來獲取模塊的日誌指針。若是是root模塊,直接用Logger::getRootLogger();獲取
LoggerPtr get_logger_ptr(IN const char* user);

#endif // ZLOG4CXX_H

 

源文件
/*!
* Email: scictor@gmail.com
* Auth: scictor
* Date: 2019-9-8
* File: zlog4cxx.cpp
* Class: zlog4cxx (if applicable)
* Brief:
* Note:
 */
#include "zlog4cxx.h"

static std::string ensure_log_complete(IN const char* format,IN va_list args)
{
    if (NULL == format)
    {
        return "";
    }

    int iNum = 0;
    unsigned int uiSize = 1024;
    string strLog("");

    char *pcBuff = new(std::nothrow) char[uiSize];
    if (NULL == pcBuff)
    {
        return strLog;
    }

    while(true)
    {
        memset(pcBuff, 0,uiSize);

        iNum = vsnprintf(pcBuff, uiSize, format, args);
        if ((iNum > -1) && (iNum < (int)uiSize))
        {
            strLog = pcBuff;
            SAFE_DELETE_ARRAY(pcBuff);

            return strLog;
        }

        //若是字符串值比默認分配大,則分配更大空間
        uiSize = (iNum > -1)?(int)(iNum + 1):(uiSize * 2);
        SAFE_DELETE_ARRAY(pcBuff);

        pcBuff = new(std::nothrow) char[uiSize];
        if (NULL == pcBuff)
        {
            return strLog;
        }
    }

    SAFE_DELETE_ARRAY(pcBuff);

    return strLog;
}
/*
寫日誌函數
IN const char* module,//在log4cxx.properties文件中設置了不少個append,這個參數用來設置模塊,例如本實例中的fa
IN const LOG_LEVEL level,日誌級別 ERROR、INFO等
IN const char* file,打印日誌函數調用的文件
IN const char* function, 打印日誌的函數
IN const int line, 打印日誌的行號
IN const char* format,//打印日誌的格式 如: "%s%d%f"
... //可變參數輸入
*/
void log4cxx_package(IN const char* module,IN const LOG_LEVEL level, IN const char* file, IN const char* function,
                     IN const int line, IN const char* format, ...)
{
    if (level > LOG_FATAL_ || level < LOG_TRACE_)
    {
        return;
    }

    if (NULL == file || NULL == function || NULL == format)
    {
        return;
    }

    LoggerPtr pLogger=nullptr;
    if (module!=NULL)
    {
        pLogger=get_logger_ptr(module);
    }
    if(pLogger==NULL)
    {
         pLogger= Logger::getRootLogger();
    }

    char acTmp[30] = { 0 };
    sprintf(acTmp,"%d",line);

    va_list args;
    std::string strLog;
    strLog = "[" + std::string(file) + ":" + std::string(function) + "(" + std::string(acTmp) + ")] ";

    va_start(args, format);
    strLog += ensure_log_complete(format, args);
    va_end(args);


    switch (level)
    {
    case LOG_TRACE_:
        LOG4CXX_TRACE(pLogger, strLog.c_str());
        break;
    case LOG_DEBUG_:
        LOG4CXX_DEBUG(pLogger, strLog.c_str());
        break;
    case LOG_INFO_:
        LOG4CXX_INFO(pLogger, strLog.c_str());
        break;
    case LOG_WARN_:
        LOG4CXX_WARN(pLogger, strLog.c_str());
        break;
    case LOG_ERROR_:

        LOG4CXX_ERROR(pLogger, strLog.c_str());
        break;
    case LOG_FATAL_:
        LOG4CXX_FATAL(pLogger, strLog.c_str());
        break;
    default:
        break;
    }

    return;
}

void log4cxx_init(IN const char* conffile)//初始化日誌庫
{
    // 讀取配置文件
    using namespace log4cxx;
    PropertyConfigurator::configure(File(conffile));
    return ;
}

LoggerPtr get_logger_ptr(IN const char* user)//獲取日誌模塊指針
{
    // 創建logger
    return Logger::getLogger(user);
}

 

4. 測試

/*!
* Email: scictor@gmail.com
* Auth: scictor
* Date: 2019-9-8
* File: %{Cpp:License:FileName}
* Class: %{Cpp:License:ClassName} (if applicable)
* Brief:
* Note:
 */
#include <bits/stdc++.h>
#include "zlog4cxx.h"
using namespace std;

int main(int argc,char **argv){
    log4cxx_init("log4cxx.properties");
    char *pStr = "YES";
    FIRE_INFO("that is ok? %s", pStr);
    printf("hello world!\n");
    return 0;
}

 

編譯: 

g++11 zlog4cxx.cpp main.cpp -o xlog -llog4cxx

結果輸出

相關文章
相關標籤/搜索