在使用日志系统log4cpp之前,需要配置好log4cpp的包文件,另外注意在编译的时候,也需要加上-llog4cpp -llpthread语句。
log4cpp配置教程1
log4cpp配置教程2
日志文件中的优先级:
在LINUX的SYSLOG中,对日志内容进行分级,将分为8个级别,如下:
LOG_EMERG 系统不可用
LOG_ALERT 消息需立即处理
LOG_CRIT 重要情况
LOG_ERR 错误
LOG_WARNING 警告
LOG_NOTICE 正常情况,但较为重要
LOG_INFO 信息
LOG_DEBUG 调试信息
需要添加的头文件:
#include
#include
#include
#include
#include
#include
using std::cout;
using namespace log4cpp;
void test0()
{
//1.单例模式接收一个对象
Category &infoCategory = Category::getInstance("name");
//2.这个对象如果想要发出日志信息,那么就需要接上一个appender,appender里面设置了记录格式与信息出口
OstreamAppender appender("name", &cout);
PatternLayout *layout = new PatternLayout();
layout->setConversionPattern("%d: [%p] %m %n");
appender.setLayout(layout);
infoCategory.setAppender(appender);
//3.之后单例对象就可以设置好优先级,当大于等于设置好的级别之后才会发出,不设置的话默认就是Priority::INFO
infoCategory.setPriority(Priority::WARN);
//4.发出信息,级别由低到高
infoCategory.debug("this is a debug message");
infoCategory.info("this is a info message");
infoCategory.notice("this is a notice message");
infoCategory.warn("this is a warning message");
infoCategory.error("this is a error message");
infoCategory.crit("this is a critical message");
infoCategory.alert("this is a alert message");
infoCategory.emerg("this is a emerge message");
Category::shutdown();
}
output
:
root@linux:/home/wwx/week2/log4cpp# g++ main.cpp -o main -llog4cpp -lpthread -g
root@linux:/home/wwx/week2/log4cpp# ./main
2020-02-28 22:07:12,371: [WARN] this is a warning message
2020-02-28 22:07:12,371: [ERROR] this is a error message
2020-02-28 22:07:12,371: [CRIT] this is a critical message
2020-02-28 22:07:12,371: [ALERT] this is a alert message
2020-02-28 22:07:12,371: [FATAL] this is a emerge message
void test1()
{
Category &infoCategory = Category::getInstance("name");
OstreamAppender appender("name", &cout);
appender.setLayout(new BasicLayout());
infoCategory.setAppender(appender);
infoCategory.setPriority(Priority::WARN);
infoCategory.debug("this is a debug message");
infoCategory.info("this is a info message");
infoCategory.notice("this is a notice message");
infoCategory.warn("this is a warning message");
infoCategory.error("this is a error message");
infoCategory.crit("this is a critical message");
infoCategory.alert("this is a alert message");
infoCategory.emerg("this is a emerge message");
Category::shutdown();
}
output
:
root@linux:/home/wwx/week2/log4cpp# g++ main.cpp -o main -llog4cpp -lpthread -g
root@linux:/home/wwx/week2/log4cpp# ./main
1582898865 WARN name : this is a warning message
1582898865 ERROR name : this is a error message
1582898865 CRIT name : this is a critical message
1582898865 ALERT name : this is a alert message
1582898865 FATAL name : this is a emerge message
void test2()
{
Category &log = Category::getInstance("log");
FileAppender appender("appender", "file.log");
PatternLayout *layout = new PatternLayout();
layout->setConversionPattern("%d:%m %n");
appender.setLayout(layout);
log.setAppender(appender);
log.debug("this is a debug message");
log.info("this is a info message");
log.notice("this is a notice message");
log.warn("this is a warning message");
log.error("this is a error message");
log.crit("this is a critical message");
log.alert("this is a alert message");
log.emerg("this is a emerge message");
Category::shutdown();
}
回滚文件(RollingFileAppender), 在之前将日志系统输入到file.log的过程中,file.log会一直增大,如果设置成为回滚文件,那么每个文件的大小是固定的,文件回滚则意味着不断对固定大小的文件进行重写,只保留最新的记录
题目:输出100条数据,并分别记录到文件与回滚文件中进行比较。
注意: PatterLayout不能只设置一个layout然后适用于所有的Appender, 必须每一个Appender都设置一个新的layout
void test3()
{
PatternLayout *layout = new PatternLayout();
layout->setConversionPattern("%d: [%p] %m %n");
PatternLayout *layout2 = new PatternLayout();
layout2->setConversionPattern("%d: [%p] %m %n");
FileAppender fileapp("fileapp", "file.log");
fileapp.setLayout(layout);
RollingFileAppender rollfileapp("rollfileapp", "rollfile.log", 1024, 3);
rollfileapp.setLayout(layout2);
Category &root = Category::getInstance("root");
root.setAppender(fileapp);
root.addAppender(rollfileapp);
root.setPriority(Priority::DEBUG);
for (int i = 0; i < 100; i++)
{
root.debug("this is a debug message");
root.info("this is a info message");
root.notice("this is a notice message");
root.warn("this is a warning message");
root.error("this is a error message");
root.crit("this is a critical message");
root.alert("this is a alert message");
root.emerg("this is a emerge message");
}
Category::shutdown();
}
Mylog.h
:
#ifndef _WD_MYLOG_H_
#define _WD_MYLOG_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
using std::setw;
using std::cout;
using std::string;
using std::stringstream;
using namespace log4cpp;
namespace wd
{
//使用单例模式
class Mylog
{
public:
void warn(const char *msg);
void error(const char *msg);
void debug(const char *msg);
void info(const char *msg);
static Mylog *getInstance();
static void destory();
private:
Mylog();
~Mylog();
private:
static Mylog *_pInstance;
Category &_root;
};
Mylog *Mylog::getInstance()
{
if (!_pInstance)
{
_pInstance = new Mylog();
}
return _pInstance;
}
Mylog::Mylog()
: _root(Category::getRoot().getInstance("rootCategory"))
{
OstreamAppender *Osappender = new OstreamAppender("Osappender", &cout);
PatternLayout *layout1 = new PatternLayout();
layout1->setConversionPattern("%d: [%p] %m %n");
Osappender->setLayout(layout1);
_root.addAppender(Osappender);
_root.setPriority(Priority::DEBUG);
_root.info("Mylog()");
}
Mylog::~Mylog()
{
_root.info("~Mylog()");
}
void Mylog::destory()
{
if (_pInstance){
delete _pInstance;
_pInstance = NULL;
}
Category::shutdown();
}
void Mylog::warn(const char *msg)
{
stringstream ss;
ss << "\""<< msg << "\"" << setw(10) <<"FileName:" << __FILE__ << setw(10) <<" Function():" << __FUNCTION__ << setw(10) <<" LINE:" << __LINE__;
_root.warn(ss.str());
}
void Mylog::info(const char *msg)
{
stringstream ss;
ss << "\""<< msg << "\"" << setw(10) <<"FileName:" << __FILE__ << setw(10) <<" Function():" << __FUNCTION__ << setw(10) <<" LINE:" << __LINE__;
_root.info(ss.str());
}
void Mylog::debug(const char *msg)
{
stringstream ss;
ss << "\""<< msg << "\"" << setw(10) <<"FileName:" << __FILE__ << setw(10) <<" Function():" << __FUNCTION__ << setw(10) <<" LINE:" << __LINE__;
_root.debug(ss.str());
}
void Mylog::error(const char *msg)
{
stringstream ss;
ss << "\""<< msg << "\"" << setw(10) <<"FileName:" << __FILE__ << setw(10) <<" Function():" << __FUNCTION__ << setw(10) <<" LINE:" << __LINE__;
_root.error(ss.str());
}
//*************下面将Mylog中的函数直接定义为内联函数,可以直接调用**************//
Mylog *Mylog::_pInstance = NULL;
Mylog *log = Mylog::getInstance();
inline void LogError(const char* msg){log->error(msg);}
inline void LogDebug(const char* msg){log->debug(msg);}
inline void LogInfo(const char* msg){log->info(msg);}
inline void LogWarn(const char* msg){log->warn(msg);}
} // namespace wd
#endif
main.cpp
:
#include "Mylog.h"
using namespace wd;
int main(){
LogError("HelloW");
LogWarn("wan");
LogInfo("info");
return 0;
}
/*
作业要求:
1.输出的日志信息能同时输出到终端和文件
2.输出的日志信息中最好能有文件的名字,函数的名字及其所在的行号
3.使用单例模式
*/
output
:
wwx@linux:~/week2/homework6$ g++ main.cpp -o main -llog4cpp -lpthread -g
wwx@linux:~/week2/homework6$ ./main
2020-03-01 14:26:47,740: [INFO] Mylog()
2020-03-01 14:26:47,740: [WARN] "HelloW" FileName:Mylogger.h Function():error LINE:100
2020-03-01 14:26:47,740: [WARN] "wan" FileName:Mylogger.h Function():warn LINE:79
2020-03-01 14:26:47,740: [WARN] "info" FileName:Mylogger.h Function():info LINE:86
如果想log4cpp输出类似于printf一样的语句,需要用到模板来重新实现:
LogInfo("this is an info message. number = %d, str = %s\n", number, pstr);
下面是改进之后的代码,如果不需要的话,也可以直接就用版本一。
Mylog.h
:
#ifndef _WD_MYLOG_H_
#define _WD_MYLOG_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
using std::cout;
using std::endl;
using std::setw;
using std::string;
using std::stringstream;
using namespace log4cpp;
namespace wd
{
//****************************定义输出格式Myprintf函数****************************//
void Myprintf(stringstream &ss, const char *str)
{
ss << str;
}
template <typename T, typename... Args>
void Myprintf(stringstream &ss, const char *str, const T &val, Args... args)
{
int i = 0;
while (str[i])
{
if (str[i] == '%')
{
char c = str[i + 1];
switch (c)
{
case 'd':
ss << val;
Myprintf(ss, str + i + 2, args...);
return;
case 'c':
ss << val;
Myprintf(ss, str + i + 2, args...);
return;
case 's':
ss << val;
Myprintf(ss, str + i + 2, args...);
return;
default:
ss << "Wrong!Error has happended!" << endl;
exit(-1);
}
}
else
{
ss << str[i++];
}
}
}
//**************************申明并定义Mylog类***************************//
class Mylog
{
public:
template <typename... Args>
void error(const char *msg, Args... args);
template <typename... Args>
void warn(const char *msg, Args... args);
template <typename... Args>
void debug(const char *msg, Args... args);
template <typename... Args>
void info(const char *msg, Args... args);
static Mylog *getInstance();
static void destory();
private:
Mylog();
~Mylog();
private:
static Mylog *_pInstance;
Category &_root;
};
Mylog *Mylog::getInstance()
{
if (!_pInstance)
{
_pInstance = new Mylog();
}
return _pInstance;
}
Mylog::Mylog()
: _root(Category::getRoot().getInstance("rootCategory"))
{
OstreamAppender *Osappender = new OstreamAppender("Osappender", &cout);
PatternLayout *layout1 = new PatternLayout();
layout1->setConversionPattern("%d: [%p] %m %n");
Osappender->setLayout(layout1);
_root.addAppender(Osappender);
_root.setPriority(Priority::DEBUG);
_root.info("Mylog()");
}
Mylog::~Mylog()
{
_root.info("~Mylog()");
}
void Mylog::destory()
{
if (_pInstance)
{
delete _pInstance;
_pInstance = NULL;
}
Category::shutdown();
}
template <typename... Args>
void Mylog::warn(const char *msg, Args... args)
{
stringstream ss;
stringstream temp;
Myprintf(temp, msg, args...);
ss << "\"" << temp.str() << "\"" << setw(10) << "FileName:" << __FILE__ << setw(10) << " Function():" << __FUNCTION__ << setw(10) << " LINE:" << __LINE__;
_root.warn(ss.str());
}
template <typename... Args>
void Mylog::info(const char *msg, Args... args)
{
stringstream ss;
stringstream temp;
Myprintf(temp, msg, args...);
ss << "\"" << temp.str() << "\"" << setw(10) << "FileName:" << __FILE__ << setw(10) << " Function():" << __FUNCTION__ << setw(10) << " LINE:" << __LINE__;
_root.info(ss.str());
}
template <typename... Args>
void Mylog::debug(const char *msg, Args... args)
{
stringstream ss;
stringstream temp;
Myprintf(temp, msg, args...);
ss << "\"" << temp.str() << "\"" << setw(10) << "FileName:" << __FILE__ << setw(10) << " Function():" << __FUNCTION__ << setw(10) << " LINE:" << __LINE__;
_root.debug(ss.str());
}
template <typename... Args>
void Mylog::error(const char *msg, Args... args)
{
stringstream ss;
stringstream temp;
Myprintf(temp, msg, args...);
ss << "\"" << temp.str() << "\"" << setw(10) << "FileName:" << __FILE__ << setw(10) << " Function():" << __FUNCTION__ << setw(10) << " LINE:" << __LINE__;
_root.error(ss.str());
}
//*************下面将Mylog中的函数直接定义为内联函数,可以直接调用**************//
Mylog *Mylog::_pInstance = NULL;
Mylog *log = Mylog::getInstance();
template <typename... Args>
inline void LogError(const char *msg, Args... args)
{
log->error(msg, args...);
}
template <typename... Args>
inline void LogWarn(const char *msg, Args... args)
{
log->warn(msg, args...);
}
template <typename... Args>
inline void LogInfo(const char *msg, Args... args)
{
log->info(msg, args...);
}
template <typename... Args>
inline void LogDebug(const char *msg, Args... args)
{
log->debug(msg, args...);
}
} // namespace wd
#endif
main.cpp
:
#include "Mylog.h"
using namespace wd;
int main(){
LogError("Hello%d %d %c %s", 1,2,'3', "456");
LogWarn("wan");
LogInfo("info");
LogDebug("debug");
return 0;
}
output
:
wwx@linux:~/week3/homework_mylog$ g++ main.cpp -llog4cpp -lpthread
wwx@linux:~/week3/homework_mylog$ ./a.out
2020-03-08 22:29:00,215: [INFO] Mylog()
2020-03-08 22:29:00,216: [ERROR] "Hello1 2 3 456" FileName:Mylog.h Function():error LINE:159
2020-03-08 22:29:00,216: [WARN] "wan" FileName:Mylog.h Function():warn LINE:129
2020-03-08 22:29:00,216: [INFO] "info" FileName:Mylog.h Function():info LINE:139
2020-03-08 22:29:00,216: [DEBUG] "debug" FileName:Mylog.h Function():debug LINE:149