-
前言
本篇接上一篇《imx6移植log4cplus库》。
-
在程序中配置
主程序:
#include <log4cplus/log4cplus.h>
using namespace std;
using namespace log4cplus;
int main()
{
//用Initializer类初始化, 根据官方文档建议,放在main()函数最开始位置,替代旧版的log4cplus::initialize()函数
log4cplus::Initializer initializer;
//第1步:创建FileAppender,个人对日志需求是滚动更新且保留最新的,故使用RollingFileAppender
log4cplus::SharedAppenderPtr fileAppender(new log4cplus::RollingFileAppender(
LOG4CPLUS_TEXT("/var/log/GuidanceLog/GuidanceLog"),
204800, 2, true, true
)
);
//第2步:设置FileAppender使用PatternLayout
fileAppender->setName(LOG4CPLUS_TEXT("guidance"));
log4cplus::tstring pattern = LOG4CPLUS_TEXT("%d{%y/%m/%d %H:%M:%S.%q} - %m%n");
fileAppender->setLayout(std::unique_ptr<log4cplus::Layout>(new log4cplus::PatternLayout(pattern)));
//第3步:创建一个Logger实例,并设置其日志输出等级
log4cplus::Logger guidanceLog = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT ("guidance"));
guidanceLog.setLogLevel(log4cplus::INFO_LOG_LEVEL);
//第4步:为Logger实例添加FileAppender
guidanceLog.addAppender(fileAppender);
//第5步:使用宏将日志输出
for(int i = 0, j = 0; i < 10000; i++,j--){
LOG4CPLUS_INFO(guidanceLog, "i = "<<i<<" j = "<<j);
}
return 0;
}
RollingFileAppender构造函数如下:
RollingFileAppender(const log4cplus::tstring& filename,
long maxFileSize = 10*1024*1024, // 10 MB
int maxBackupIndex = 1,
bool immediateFlush = true,
bool createDirs = false);
函数参数解释:
filename:文件名,即日志保存到哪个文件,一般推荐用绝对路径,如:“/var/log/test”
MaxFileSize:输出文件的最大大小,默认值10*1024*1024 bytes(即10MB)。实际测试最小值为204800(即200kb),若设置值小于该值,则自动设为204800,且输出以下警告信息:
log4cplus:WARN RollingFileAppender: MaxFileSize property value is too small. Resetting to 204800.
注:该值若在配置文件中配置则支持MB和KB为后缀的值,如1MB、500KB.
MaxBackupIndex: 日志文件的最大索引,用于限制输出日志文件的个数,默认值1。若该值为1,则最多只生成两个文件,如log,log.1;若该值为2,则最多生成三个文件,如log,log.1,log.2,以此类推。新日志会滚动覆盖旧日志。索引号越大,日志信息越旧!不带索引号(可理解为0)为最新的日志。如log.2是最旧的,log是最新的。
immediateFlush :true = 每次有append event事件,输出流就会被刷新到文件中;若为false,当程序崩溃时,很有可能最后几个日志事件实际上没有写入文件
createDirs :true = 指定的日志路径名中如果有文件夹不存在,则会创建文件夹;false = 与上述相反。此时,若路径中文件夹不存在,则将报错:
log4cplus:ERROR Unable to open file: ……
-
使用配置文件
配置文件:log.cfg
#配置格式:
#root logger: log4cplus.rootLogger=[LogLevel], appenderName, appenderName, ...
#non-root loggers: log4cplus.logger.logger_name=[LogLevel|INHERITED], appenderName, appenderName, ...
#LogLevel: TRACE,DEBUG,INFO,WARN,ERROR,FATAL
#logger_name与实例化的对象名一致
#配置GuidanceLog
log4cplus.logger.guidance=TRACE, A1
log4cplus.appender.A1=log4cplus::RollingFileAppender
log4cplus.appender.A1.File=/var/log/GuidanceLog/GuidanceLog
log4cplus.appender.A1.MaxFileSize=200KB # 1MB
log4cplus.appender.A1.MaxBackupIndex=3
log4cplus.appender.A1.ImmediateFlush=true
log4cplus.appender.A1.CreateDirs=true
log4cplus.appender.A1.layout=log4cplus::PatternLayout
log4cplus.appender.A1.layout.ConversionPattern=%d{%y/%m/%d %H:%M:%S.%q} - %m%n
#配置其它Log同上
主程序:
#include <log4cplus/log4cplus.h>
using namespace std;
using namespace log4cplus;
int main()
{
//用Initializer类进行初始化
log4cplus::Initializer initializer;
//读取配置文件,参数即为配置文件路径
PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("./log.cfg"));
//创建Logger实例
Logger guidanceLog = log4cplus::Logger::getInstance("guidance");
//使用宏将日志输出
for(int i = 0, j = 0; i < 10000; i++,j--){
LOG4CPLUS_TRACE(guidanceLog, "i = "<<i<<" j = "<<j);
}
return 0;
}
运行后,在/var/log下新建GuidanceLog文件夹,并保存最多4个日志文件:
![]()
打开最新的GuidanceLog文件,如下:

相比较而言,一般建议使用配置文件,后期若想对日志文件进行调整,不需要去修改源代码,只需修改配置文件即可。
-
结束
优快云中很多文章所附的官方API参考链接已经失效了,此处更新:
ps:相比较pugixml库的官方参考手册,这个参考手册对新手的确不是很友好 ~~o(>_<)o ~~
2022-3-9 更新
本想简单封装一下,Log_C为封装后的类名,并将以下两步封装成一个初始化函数:
//用Initializer类进行初始化
log4cplus::Initializer initializer;
//读取配置文件,参数即为配置文件路径
PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("./log.cfg"));
void Log_C::initLogger(const string &cfgFilePath)
{
//用Initializer类进行初始化
log4cplus::Initializer initializer;
//读取配置文件,参数即为配置文件路径
PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT(cfgFilePath));
}
然后在main函数中调用,发现报错:
int main()
{
Log_C::initLogger("log.cfg");
/** 省略 **/
}
报错如下:

看信息猜测是初始化方式不对??
然后,把:
log4cplus::Initializer initializer;
移动到封装的函数之外再试:
void Log_C::initLogger(const string &cfgFilePath)
{
// //用Initializer类进行初始化
// log4cplus::Initializer initializer; //移到函数外,直接在main函数执行
//读取配置文件,参数即为配置文件路径
PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT(cfgFilePath));
}
int main() {
//用Initializer类进行初始化
log4cplus::Initializer initializer;
Log_C::initLogger("log.cfg");
/** 省略 **/
}
可行!!
所以, 结论是:log4cplus的初始化应该直接放在main函数下执行?不可通过其它函数调用的方式?有待研究。
2022-3-10更新
今天又经过了一番测试,发现:“用Initializer类进行初始化”和“读取配置文件”这两步骤不可放在同一个函数中调用。接着昨天的测试,单独将Initializer初始化移出初始化函数或单独将读取配置文件移出初始化函数,就都正常了。原因不明,暂搁置。
作为解决方案,把初始化和读取配置文件分成两个静态成员函数来实现。
2022-3-31 更新
如果想在程序中关闭相应级别日志的输出,比如DEBUG级别的,可使用宏定义:
#define LOG4CPLUS_DISABLE_DEBUG
但是,宏定义需要放在包含log4cplus库的头文件的前面,如
#define LOG4CPLUS_DISABLE_DEBUG
#include <log4cplus/log4cplus.h>
遗留问题:宏定义的开启或关闭是全局的,如果想在每个cpp文件中单独控制开启或关闭,如何实现?因为调试程序时,当某个cpp模块调试好了,就把这个模块的所有debug信息关闭,不用输出。但是当前正在调试的模块则需要输出。使用log4cplus如何实现,待研究。
2529



被折叠的 条评论
为什么被折叠?



