一起学习log4cxx
阅读原文时间:2023年07月11日阅读:1

目前成熟的日志系统有很多,比如log4cxx,log4cpp等,今天一起来学习log4cxx吧,之所以学习这个,首先,这个日志库比较成熟,一直由apach基金在维护,而log4cpp缺乏维护.再者,这个库的性能相对高一些,大约为10w行/s.

log4cxx依赖于apach的另外两个开源库apr和apr-util.

准备工作:

首先下载 apr-1.7.0.tar.gz, apr-util-1.6.1.tar.gzlog4cxx库

百度网盘

提取码: kzwc

1. 安装依赖库apr和apr-util

#首先解压压缩包
$ tar -zxvf apr-1.7..tar.gz
$ cd apr-1.7.

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

#首先解压压缩包
$ tar -zxvf apr-util-1.6..tar.gz
$ cd apr-util-1.6.

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

2.安装log4cxx

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

安装log4cxx可能会报错:

解决办法:

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
4 src/main/cpp/socketoutputstream.cpp添加#include
5 src/examples/cpp/console.cpp添加#include ;#include

**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
#include
#include
#include
#include
#include
#include

using namespace log4cxx;
using namespace log4cxx::helpers;
#include
using namespace std;
#define SAFE_DELETE_ARRAY(v_para)\
do \
{\
if (NULL != v_para) {\
delete[] v_para;\
v_para = NULL;\
}\
} while ()
//TRACE < DEBUG < INFO < WARN < ERROR < FATAL
typedef enum _LOG_LEVEL
{
LOG_TRACE_ = ,
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 = ;  
unsigned int uiSize = ;  
string strLog("");

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

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

    iNum = vsnprintf(pcBuff, uiSize, format, args);  
    if ((iNum > -) && (iNum < (int)uiSize))  
    {  
        strLog = pcBuff;  
        SAFE\_DELETE\_ARRAY(pcBuff);

        return strLog;  
    }

    //如果字符串值比默认分配大,则分配更大空间  
    uiSize = (iNum > -)?(int)(iNum + ):(uiSize \* );  
    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\[\] = {  };  
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
#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 ;
}

编译:

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

结果输出