大家好,又见面了,我是你们的朋友全栈君。
简介
关于log4cpp的介绍与好处就不再赘言了,百度一搜一大把。主要是对于log4cpp的使用如果不封装一下,感觉还是挺麻烦的,例如不少函数名挺长的。所以自己动手把它的日常使用进行了封装,可以让使用log4cpp就像调用一句printf()函数一样简单快捷。
封装目标
- 不需要用一次就调用一次getInstance,只需要在main文件中引入一次即可
- 封装成需要使用时只需简短的一举logError(“somelog”) 就搞定
- 输出的日志内容包含:文件名,函数名,行号(通过以上函数调用即可)
- 利用单例模式封装
具体实现
类定义 & 宏定义
巧妙的使用宏定义可以缩短函数调用形式(虽然effective c 和google C 编程规范都极力反对使用太多宏)
代码语言:javascript复制#ifndef _MYLOG_H
#define _MYLOG_H
#include<log4cpp/Category.hh>
#include<iostream>
//日志优先级
enum Priority {
ERROR,
WARN,
INFO,
DEBUG
};
//用单例模式封装log4cpp
class Mylog {
public:
static Mylog& getInstance();
static void destory();
void setPriority(Priority priority);
void error(const char* msg);
void warn(const char* msg);
void info(const char* msg);
void debug(const char* msg);
private:
Mylog(); //单例模式:构造函数私有化
private:
static Mylog *plog_;
log4cpp::Category &category_ref_;
};
//*****************************************************
//注意:
//文件名 __FILE__ ,函数名 __func__ ,行号__LINE__ 是编译器实现的
//并非C 头文件中定义的
//前两个变量是string类型,且__LINE__是整形,所以需要转为string类型
//******************************************************
//整数类型文件行号 ->转换为string类型
inline std::string int2string(int line) {
std::ostringstream oss;
oss << line;
return oss.str();
}
//定义一个在日志后添加 文件名 函数名 行号 的宏定义
#define suffix(msg) std::string(msg).append(" ##")
.append(__FILE__).append(":").append(__func__)
.append(":").append(int2string(__LINE__))
.append("##").c_str()
//不用每次使用时写 getInstance语句
//只需要在主函数文件中写: #define _LOG4CPP_即可在整个程序中使用
#ifdef _LOG4CPP_
Mylog &log = Mylog::getInstance();
#else
extern Mylog &log;
#endif
//缩短并简化函数调用形式
#define logError(msg) log.error(suffix(msg))
#define logWarn(msg) log.warn(suffix(msg))
#define logInfo(msg) log.info(suffix(msg))
#define logDebug(msg) log.debug(suffix(msg))
#endif
成员函数的实现:
代码语言:javascript复制#include<iostream>
#include "Mylog.h"
#include<log4cpp/PatternLayout.hh>
#include<log4cpp/OstreamAppender.hh>
#include<log4cpp/FileAppender.hh>
#include<log4cpp/Priority.hh>
using namespace std;
Mylog* Mylog::plog_ = NULL;
//获取log指针
Mylog& Mylog::getInstance() {
if ( plog_ == NULL ) {
plog_ = new Mylog;
}
return *plog_;
}
//销毁
void Mylog::destory() {
if (plog_) {
plog_->category_ref_.info("Mylog destroy");
plog_->category_ref_.shutdown();
delete plog_;
}
}
//构造函数
Mylog::Mylog():
category_ref_(log4cpp::Category::getRoot()) {
//自定义输出格式
log4cpp::PatternLayout *pattern_one =
new log4cpp::PatternLayout;
pattern_one->setConversionPattern("%d: %p %c %x:%m%n");
log4cpp::PatternLayout *pattern_two =
new log4cpp::PatternLayout;
pattern_two->setConversionPattern("%d: %p %c %x:%m%n");
//获取屏幕输出
log4cpp::OstreamAppender *os_appender =
new log4cpp::OstreamAppender("osAppender",&std::cout);
os_appender->setLayout(pattern_one);
//获取文件日志输出 ( 日志文件名:mylog.txt )
log4cpp::FileAppender *file_appender =
new log4cpp::FileAppender("fileAppender","mylog.txt");
file_appender->setLayout(pattern_two);
category_ref_.setPriority(log4cpp::Priority::DEBUG);
category_ref_.addAppender(os_appender);
category_ref_.addAppender(file_appender);
category_ref_.info("Mylog created!");
}
//设置优先级
void Mylog::setPriority(Priority priority) {
switch (priority) {
case (ERROR):
category_ref_.setPriority(log4cpp::Priority::ERROR);
break;
case (WARN):
category_ref_.setPriority(log4cpp::Priority::WARN);
break;
case (INFO):
category_ref_.setPriority(log4cpp::Priority::INFO);
break;
case (DEBUG):
category_ref_.setPriority(log4cpp::Priority::DEBUG);
break;
default:
category_ref_.setPriority(log4cpp::Priority::DEBUG);
break;
}
}
void Mylog::error(const char* msg) {
category_ref_.error(msg);
}
void Mylog::warn(const char* msg) {
category_ref_.warn(msg);
}
void Mylog::info(const char* msg) {
category_ref_.info(msg);
}
void Mylog::debug(const char* msg) {
category_ref_.debug(msg);
}
这样就大致完成了满足前述目标的封装了。 假如程序中有一个func.h的头文件,其实现文件时func.cpp,如下所示:
func.h:
代码语言:javascript复制#ifndef _FUNC_H
#define _FUNC_H
void func();
#endif
func.cpp:
代码语言:javascript复制/*************************************************************************
> File Name: func.cpp
> Author:
> Mail:
> Created Time: Thu 30 Jul 2015 06:54:49 AM PDT
************************************************************************/
#include<iostream>
#include "func.h"
#include"Mylog.h"
using namespace std;
void func() {
logError("hello allen,func() called");
}
测试程序:
只需要在主函数中加入第一行语句 #define LOG4CPP (注意需要在第一行引入) 而其他头文件或实现文件中都不需要再添加任何语句引入log4cpp,都可以畅通无阻地使用了
代码语言:javascript复制#define _LOG4CPP_
#include<iostream>
#include "Mylog.h"
#include "func.h"
using namespace std;
int main(void) {
//Mylog& log = Mylog::getInstance();
//log.setPriority(ERROR);
logError("error allen");
logWarn("warn allen");
func();
return 0;
}
运行结果:
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/158415.html原文链接:https://javaforall.cn