一起学习log4cxx
目前成熟的日志系统有很多,比如log4cxx,log4cpp等,今天一起来学习log4cxx吧,之所以学习这个,首先,这个日志库比较成熟,一直由apach基金在维护,而log4cpp缺乏维护.再者,这个库的性能相对高一些,大约为10w行/s.
log4cxx依赖于apach的另外两个开源库apr和apr-util.
准备工作:
首先下载 apr-1.7.0.tar.gz, apr-util-1.6.1.tar.gz和log4cxx库
提取码: 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可能会报错:
解决办法:
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
结果输出