实现log4cpp的封装,使其可以像printf一样使用,测试用例如下:
void test()
{
int number = 100;
const char *pstr = "hello, log4cpp";
LogInfo("This is an info message. number = %d, str = %s\n", number, pstr);
}
------------ Mylogger.h------------
#ifndef __MYLOGGER__H__
#define __MYLOGGER__H__
#include <log4cpp/Category.hh>
#define LOGFILENAME "test.log"
using namespace log4cpp;//导入全部log4cpp的全部实体
class Mylogger
{
public:
static Mylogger *getInstance();
static void destroy();
void warn(const char * msg);
void error(const char * msg);
void debug(const char * msg);
void info(const char * msg);
template <class... Args>
//不能把函数的实现写在Mylogger.cc中
//和inline一样,函数的实现和声明不能分开,否则会链接失败
void warn(const char * msg, Args... args)
{
_root.warn(msg, args...);
}
template <class... Args>
void error(const char * msg, Args... args)
{
_root.error(msg, args...);
}
template <class... Args>
void info(const char * msg, Args... args)
{
_root.info(msg, args...);
}
template <class... Args>
void debug(const char * msg, Args... args)
{
_root.debug(msg, args...);
}
private:
Mylogger();
~Mylogger();
private:
static Mylogger *_pInstance;
Category &_root; //引用成员必须在构造函数的初始化列表进行初始化,否则会报错
};
//文件名、行号、函数名相关,这里没用到不用管
#define prefic(msg) string(__FILE__).append(" ").append(__FUNCTION__) \
.append(" ").append(std::to_string(__LINE__))\
.append(":").append(msg).c_str()
//##__VA_ARGS__接收可变数目的参数,当宏的调用展开时,实际的参数就传递给函数了
#define logError(msg,...) Mylogger::getInstance()->error(msg,##__VA_ARGS__)
#define logInfo(msg,...) Mylogger::getInstance()->info(msg,##__VA_ARGS__)
#define logDebug(msg,...) Mylogger::getInstance()->debug(msg,##__VA_ARGS__)
#define logWarn(msg,...) Mylogger::getInstance()->warn(msg,##__VA_ARGS__)
//##的用处:当只有msg参数时,忽略后面的,号
#endif
------------ Mylogger.cc------------
#include "Mylogger.h"
#include <stdlib.h>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/FileAppender.hh>
using std::cout;
using std::endl;
Mylogger * Mylogger::_pInstance=Mylogger::getInstance(); //必须在实现文件中初始化,在头文件中初始化易出现重复定义
Mylogger::Mylogger()
:_root(Category::getRoot().getInstance("Mycat")) //获得日志记录器,记录器名为Mycat
{
//设置日志的格式
//文件格式
PatternLayout *ppl1 = new PatternLayout();
ppl1->setConversionPattern("%d %c [%p] %m %n");
//终端格式
PatternLayout *ppl2 = new PatternLayout();
ppl2->setConversionPattern("%d %c [%p] %m %n");
//设置日志输出的地点
//输出到文件
FileAppender *pfa = new FileAppender("FileAppender123", LOGFILENAME);
pfa->setLayout(ppl1);
//输出到输出流对象
OstreamAppender *poa = new OstreamAppender("OstreamAppender1", &cout);
poa->setLayout(ppl2);
//绑定到记录器
_root.addAppender(poa);
_root.addAppender(pfa);
_root.setPriority(Priority::DEBUG);
cout<<"Mylogger()"<<endl;
}
void Mylogger::destroy()//销毁单例对象
{
if(_pInstance!=nullptr)
{
delete _pInstance;
_pInstance=nullptr;
}
}
Mylogger *Mylogger::getInstance()//创建单例对象
{
if(_pInstance==nullptr)
{
_pInstance=new Mylogger();
atexit(destroy);//单例模式自动释放:注册函数,进程结束时自动调用
}
return _pInstance;
}
Mylogger::~Mylogger()
{
cout<<"~Mylogger()"<<endl;
Category::shutdown();//回收日志资源
}
void Mylogger::info(const char *msg)
{
_root.info(msg);
}
void Mylogger::error(const char *msg)
{
_root.error(msg);
}
void Mylogger::warn(const char *msg)
{
_root.warn(msg);
}
void Mylogger::debug(const char *msg)
{
_root.debug(msg);
}
------------ test.cc-----------
#include "Mylogger.h"
void test()
{
int number = 100;
const char *pstr = "hello";
logInfo("This is an info message. number = %d, str = %s\n", number, pstr);
logWarn("this is a warn message!\n");
logError("this is a error message! str=%s\n",pstr);
logDebug("this is a debug message!,number=%d\n",number);
}
int main(int argc,char *argv[])
{
test();
return 0;
}