log4cpp的使用

log4cpp的使用

逻辑构造

目的地Appender:用于表示日志系统最后输出到哪
布局Layout:表示你输出的格式,类似与printf
优先级Priority:常见的优先级有emerg,alert,crit,error,warn,notice,info,debug,优先级从高到低排列,优先级主要针对不同用户设定,如果一个用户设定的优先级是warn,那么notice,info,debug的信息就会忽略掉不输出
日志Category:是整个日志系统的主干,目的地的设定添加和模板设置,日志记录都由Category完成

一个目的地只能有一个布局,一个布局对应一个目的地

基本模板

#include <iostream>
#include <log4cpp/OstreamAppender.hh> 
#include <log4cpp/Appender.hh>
#include <log4cpp/BasicLayout.hh>
#include <log4cpp/Category.hh>
#include <log4cpp/Priority.hh>

using std::cout;
using namespace log4cpp;

void test0()
{
	//设置目的地对象
	//参数1 目的地的名字 console代表控制台,
	//参数2 流对象
	OstreamAppender* posAp = new OstreamAppender("console", &cout);

	//设置目的地布局 BasicLayout函数是创建布局对象
	posAp->setLayout(new BasicLayout());
	
	//创建日志对象,getRoot函数返回的是创建的日志对象,用引用符号接取
	Category& root = Category::getRoot();
	
	//设置日志的目的地
	root.setAppender(posAp);
	//设置日志的优先级
	root.setPriority(Priority::DEBUG);

	//设置模板
	Category& model1 = root.getInstance("register");

	//打印日志记录
	root.emerg("this is an emrge");
	root.alert("this is an alert");
	root.crit("this is a critical");
	root.error("this is an error");
	root.warn("this is a warn");
	root.notice("this is a notice");
	root.info("this is an info");
	root.debug("this is a debug");

	model1.debug("123456");
}
int main()
{
	test0();

	return 0;
}

输出结果

1684758947 FATAL  : this is an emrge
1684758947 ALERT  : this is an alert
1684758947 CRIT  : this is a critical
1684758947 ERROR  : this is an error
1684758947 WARN  : this is a warn
1684758947 NOTICE  : this is a notice
1684758947 INFO  : this is an info
1684758947 DEBUG  : this is a debug
1684758947 DEBUG register : 123456

打印第一列代表时间,单位为秒,第二列为优先级,第三列为模块名,root没有设置所以是空白,最后面为日志内容

布局的格式化

类似于priintf函数,常以%d代表输出十进制,Layout对象也有着类似的表达方式

PatternLayout

setConversionPattern成员函数,PatternLayout的格式化函数
%c 获取模块名
%d 打印日期时间,将第一列时间单位为秒转化为可读性时间
%m 打印消息内容
%p 打印优先级
%n 换行符

#include <iostream>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/Category.hh>
#include <log4cpp/Priority.hh>

using namespace log4cpp;
using std::cout;

void test0()
{
	OstreamAppender* posAp = new OstreamAppender("console", &cout);

	//设置格式化布局
	PatternLayout* ptnLayout = new PatternLayout();
	ptnLayout->setConversionPattern("%d [%c] [%p] %m %n");

	posAp->setLayout(ptnLayout);

	Category& root = Category::getRoot();

	root.setAppender(posAp);
	root.setPriority(Priority::DEBUG);

	Category& model1 = root.getInstance("register");

	model1.emerg("this is an emerg");
	root.emerg("this is an emerg");
	
	Category::shutdown();
}
int main()
{
	test0();
}

输出结果

2023-05-23 18:57:33,748 [register] [FATAL] this is an emerg
2023-05-23 18:57:33,749 [] [FATAL] this is an emerg

目的地对象操作文件

FileAppender

参数列表
参数1 目的地名字
参数2 文件名
参数3 是否以追加模式写入(默认追加)
参数4 文件权限(不写以默认权限为主)
#include <iostream>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/BasicLayout.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/Category.hh>
#include <log4cpp/Priority.hh>

using namespace log4cpp;
using std::cout;

void test0()
{
	//两个目的地对象创建,最后一个输出在控制台一个写入到文件中去
	OstreamAppender* posAp = new OstreamAppender("console", &cout);
	FileAppender* FileAp = new FileAppender("FileAp", "test.log");

	PatternLayout* ptnLayout = new PatternLayout();
	ptnLayout->setConversionPattern("%d [%c] [%p] %m %n");

	//让目的地为控制台的对象打印普通日志信息
	//让目的地为文件的对象打印格式化日志信息
	posAp->setLayout(new BasicLayout());
	FileAp->setLayout(ptnLayout);

	Category& root = Category::getRoot();
	root.setAppender(posAp);
	//追加目的地
	root.addAppender(FileAp);
	root.setPriority(Priority::DEBUG);

	Category& model = root.getInstance("register");

	root.emerg("root emerg");
	root.alert("root alert");
	root.crit("root crit");
	root.error("root error");
	root.warn("root warn");
	root.notice("root notice");
	root.info("root info");
	root.debug("root debug");

	model.emerg("model emerg");
	model.debug("model debug");

	Category::shutdown();
}
int main()
{
	test0();
}

输出结果

1684840653 FATAL  : root emerg
1684840653 ALERT  : root alert
1684840653 CRIT  : root crit
1684840653 ERROR  : root error
1684840653 WARN  : root warn
1684840653 NOTICE  : root notice
1684840653 INFO  : root info
1684840653 DEBUG  : root debug
1684840653 FATAL register : model emerg
1684840653 DEBUG register : model debug

同时在该项目目录下可以找到之前生成的文件test.log
在这里插入图片描述
打开后可看到日志内容(我这里生成了两次所以上下时间不同,写入了两次,也可以看出FileAppender默认是以追加模式进行写入的)在这里插入图片描述

回卷文件

RollingFileAppender

应用场景:用于一些对于存储空间要求较高,不希望日志文件占用过多空间
回卷文件说明:假如一次产生连续十个回卷文件,编号为1-10,要求日志文件只能占10M空间,那么每个回卷文件最大大小为1M,当日志信息填入回卷文件1且填满时,会使用回卷文件2继续写入,当10个回卷文件都填满时,会删除最早的回卷文件,重新写入数据,在当前场景下,回卷文件1是最早的一个,于是将他重定向操作,这种结构类似于队列一样,也有着先进先出的特点(再严谨一点是循环队列)

参数列表
参数1 目的地名字
参数2 文件名
参数3 每个文件大小,单位为字节,5000则为5KB
参数4 需要多少个回卷文件

#include <iostream>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/RollingFileAppender.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/BasicLayout.hh>
#include <log4cpp/Category.hh>
#include <log4cpp/Priority.hh>

using namespace log4cpp;
using std::cout;

void test0()
{
	//设置三个对象,分别对应控制台,文件,回卷文件
	OstreamAppender* posAp = new OstreamAppender("console",&cout);
	FileAppender* FileAp = new FileAppender("FileAp","test.log");
	RollingFileAppender* RollingFileAp = new RollingFileAppender("RollingFileAp","a.log",5000,10);
	
	PatternLayout* ptnLayout1 = new PatternLayout();
	PatternLayout* ptnLayout2 = new PatternLayout();
	ptnLayout2->setConversionPattern("%d [%c] [%p] %m %n");
	ptnLayout2->setConversionPattern("%d [%c] [%p] %m %n");
	//一个目的地只能对应一个布局,一个布局只能对应一个目的地
	
	posAp->setLayout(new BasicLayout());
	FileAp->setLayout(ptnLayout1);
	RollingFileAp->setLayout(ptnLayout2);
	
	Category& root = Category::getRoot();
	root.setAppender(posAp);
	root.addAppender(FileAp);
	root.addAppender(RollingFileAp);
	root.setPriority(Priority::DEBUG);
	
	Category& model = root.getInstance("register");
	
	for(int i = 0;i < 100;++i)
	{
		root.emerg("this is an emrge");
		root.alert("this is an alert");
		root.crit("this is a critical");
		root.error("this is an error");
		root.warn("this is a warn");
		root.notice("this is a notice");
		root.info("this is an info");
		root.debug("this is a debug");
	
		model.emerg("this is an emrge");
		model.alert("this is an alert");
		model.crit("this is a critical");
		model.error("this is an error");
		model.warn("this is a warn");
		model.notice("this is a notice");
		model.info("this is an info");
		model.debug("this is a debug");
	}
	
	Category::shutdown;
}
int main()
{
	test0();
	
	return 0;
}

输出结果

1684842384 FATAL  : this is an emrge
1684842384 ALERT  : this is an alert
1684842384 CRIT  : this is a critical
1684842384 ERROR  : this is an error
1684842384 WARN  : this is a warn
1684842384 NOTICE  : this is a notice
1684842384 INFO  : this is an info
1684842384 DEBUG  : this is a debug
1684842384 FATAL register : this is an emrge
1684842384 ALERT register : this is an alert
1684842384 CRIT register : this is a critical
1684842384 ERROR register : this is an error
1684842384 WARN register : this is a warn
1684842384 NOTICE register : this is a notice
1684842384 INFO register : this is an info
1684842384 DEBUG register : this is a debug
...
...
1684842384 FATAL  : this is an emrge
1684842384 ALERT  : this is an alert
1684842384 CRIT  : this is a critical
1684842384 ERROR  : this is an error
1684842384 WARN  : this is a warn
1684842384 NOTICE  : this is a notice
1684842384 INFO  : this is an info
1684842384 DEBUG  : this is a debug
1684842384 FATAL register : this is an emrge
1684842384 ALERT register : this is an alert
1684842384 CRIT register : this is a critical
1684842384 ERROR register : this is an error
1684842384 WARN register : this is a warn
1684842384 NOTICE register : this is a notice
1684842384 INFO register : this is an info
1684842384 DEBUG register : this is a debug
1684842384 FATAL  : this is an emrge
1684842384 ALERT  : this is an alert
1684842384 CRIT  : this is a critical
1684842384 ERROR  : this is an error
1684842384 WARN  : this is a warn
1684842384 NOTICE  : this is a notice
1684842384 INFO  : this is an info
1684842384 DEBUG  : this is a debug
1684842384 FATAL register : this is an emrge
1684842384 ALERT register : this is an alert
1684842384 CRIT register : this is a critical
1684842384 ERROR register : this is an error
1684842384 WARN register : this is a warn
1684842384 NOTICE register : this is a notice
1684842384 INFO register : this is an info
1684842384 DEBUG register : this is a debug

目录下生成结果
![在这里插入图片描述](https://img-blog.csdnimg.cn/a1f4133bd1c3459587ef0281c5c029ed.png

在这里插入图片描述

在这里插入图片描述
可以看到通过FileAppender生成了test.log,文件大小为28KB
通过RollingFileAppender生成了10个a.log回卷文件,每个文件大小都为5KB,总和为50KB,此时还并不能体现出回卷文件节省空间的能力
我们把for循环改为1000次
在这里插入图片描述

此时可以看到test.log大小为899KB,a.log回卷文件大小总和依然为50KB