简述
Log4Qt 支持自定义输出,格式化由 Layout 完成,输出地则由 Appender 控制。
Appender 表示将日志输出到什么地方,常见的 Appender 有 Console(控制台)、File(文件)等等。
继承关系图
Log4Qt::Appender 继承关系图:
在该层次结构中,顶级类是 Appender,它是 Log4Qt API 中所有其他输出地的基类。
AppenderSkeleton:实现一般 Appender 的功能
通常来讲,自定义输出需要继承 AppenderSkeleton,并实现其中的几个方法。
DebugAppender:将日志事件附加到特定于平台的调试输出(在 Windows 上附加到 Debugger,其它系统上附加到 stderr)
ListAppender:将日志记录事件追加到列表中,供后续处理。
NullAppender:忽略所有要附加的请求
当然,最常用的是以下几个:
WriterAppender:将日志事件附加到 QTextStream
ConsoleAppender:附加到 stdout 或 stderr
FileAppender:将日志事件附加到文件
DailyRollingFileAppender:以指定的频率滚动日志文件
RollingFileAppender:在达到特定大小时滚动日志文件
输出到控制台
在项目开发阶段,往往需要在控制台中输出日志的内容,这对于调试代码来说非常方便。
这时,ConsoleAppender 会十分有用:
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// 创建一个 TTCCLayout(输出时间、线程、Logger 以及消息内容)
Log4Qt::Logger *logger = Log4Qt::Logger::rootLogger();
Log4Qt::TTCCLayout *layout = new Log4Qt::TTCCLayout();
layout->setName("My Layout");
layout->activateOptions();
// 创建一个 ConsoleAppender(将日志内容输出到控制台上)
Log4Qt::ConsoleAppender *appender = new Log4Qt::ConsoleAppender(layout, Log4Qt::ConsoleAppender::STDOUT_TARGET);
appender->setName("My Appender");
appender->activateOptions();
// 在 logger 上添加 appender
logger->addAppender(appender);
// 设置级别为 DEBUG
logger->setLevel(Log4Qt::Level::DEBUG_INT);
// 输出信息
logger->debug("Hello, Log4Qt!");
// 关闭 logger
logger->removeAllAppenders();
logger->loggerRepository()->shutdown();
return a.exec();
}
其中,Logger 用于提供日志记录服务,Layout 用于控制消息的输出格式。
在程序的最后,记得关闭 Logger - 删除之前添加的所有 Appender,并关闭 LoggerRepository(以释放 Appender 持有的资源)。
输出到文件
但在实际的产品阶段,我们更希望将日志输出到指定的文件中,以便后续跟踪程序的行为、定位问题。
这时,就需要用到 FileAppender:
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// 创建一个 TTCCLayout(输出时间、线程、Logger 以及消息内容)
Log4Qt::Logger *logger = Log4Qt::Logger::rootLogger();
Log4Qt::TTCCLayout *layout = new Log4Qt::TTCCLayout();
layout->setName("My Layout");
layout->activateOptions();
// 创建一个 FileAppender(将日志内容输出到文件中)
QString file = QCoreApplication::applicationDirPath() + "/debug.log";
Log4Qt::FileAppender *appender = new Log4Qt::FileAppender(layout, file, true);
appender->setName("My Appender");
appender->activateOptions();
// 在 logger 上添加 appender
logger->addAppender(appender);
// 设置级别为 DEBUG
logger->setLevel(Log4Qt::Level::DEBUG_INT);
// 输出信息
logger->debug("Hello, Log4Qt!");
// 关闭 logger
logger->removeAllAppenders();
logger->loggerRepository()->shutdown();
return a.exec();
}
在构造 FileAppender 时,可以用第三个参数指定文件的打开方式,true 表示以 Append(追加)方式打开,false 表示以 Truncate(截断) 方式打开。除此之外,也可以使用 setAppendFile(bool append)。
虽然 FileAppender 提供了对日志文件的支持,但都是一些最基本的操作。倘若要实现周期性生成日志文件、限制文件大小和个数等一些更高级的控制,则需要用到其派生类 - DailyRollingFileAppender 和 RollingFileAppender。
以指定的频率滚动日志文件
为了根据日期时间来定位日志,使其更加清晰易查,可以周期性生成日志文件(例如:DAILY_ROLLOVER 指定每天生成一个新文件),这由 DailyRollingFileAppender 来完成。
DatePattern 用于指定日期模式(频率),其有效值包括:
枚举
模式字符串
描述
MINUTELY_ROLLOVER
"'.'yyyy-MM-dd-hh-mm"
每分钟
HOURLY_ROLLOVER
"'.'yyyy-MM-dd-hh"
每小时
HALFDAILY_ROLLOVER
"'.'yyyy-MM-dd-a"
每半天
DAILY_ROLLOVER(默认值)
"'.'yyyy-MM-dd"
每天
WEEKLY_ROLLOVER
"'.'yyyy-ww"
每周
MONTHLY_ROLLOVER
"'.'yyyy-MM"
每月
注意: DatePattern 中不用处理的文字要放到单引号('')中,如上面的 '.'。
为了方便测试,以最短的间隔(每分钟)生成日志文件:
可以看到,文件名后自动加上了日期时间,很容易区分。
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// 创建一个 TTCCLayout(输出时间、线程、Logger 以及消息内容)
Log4Qt::Logger *logger = Log4Qt::Logger::rootLogger();
Log4Qt::TTCCLayout *layout = new Log4Qt::TTCCLayout();
layout->setName("My Layout");
layout->activateOptions();
// 创建一个 DailyRollingFileAppender(每分钟生成一个新文件)
QString file = QCoreApplication::applicationDirPath() + "/debug.log";
Log4Qt::DailyRollingFileAppender *appender = new Log4Qt::DailyRollingFileAppender(layout, file, "'.'yyyy-MM-dd-hh-mm");
appender->setName("My Appender");
appender->activateOptions();
// 在 logger 上添加 appender
logger->addAppender(appender);
// 设置级别为 DEBUG
logger->setLevel(Log4Qt::Level::DEBUG_INT);
int count = 0;
while (count < 10) {
// 输出信息
logger->debug("Hello, Log4Qt!");
Sleep(30 *1000);
++count;
}
// 关闭 logger
logger->removeAllAppenders();
logger->loggerRepository()->shutdown();
return a.exec();
}
要设置频率,除了可以在 DailyRollingFileAppender 的构造函数中指定一个模式字符串之外,还可以使用 setDatePattern(DatePattern datePattern) 指定一个枚举值进行设置。
在达到特定大小时滚动日志文件
随着时间的推移,日志文件会越来越多、越来越大,倘若不进行数量和大小上的限制,最后日志将会占满整个硬盘。
RollingFileAppender 使用 MaxFileSize 和 MaxBackupIndex 来限制日志文件的大小和数量。当产生多个日志文件时,会在日志名称后面加上“.1”、“.2”、… 这样的后缀。
下面,来读取一个文件,并将其内容写入到我们的日志文件中:
在此过程中,限制每个日志文件的最大大小为 10 KB,最大文件数为 5 个:
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// 创建一个 TTCCLayout(输出时间、线程、Logger 以及消息内容)
Log4Qt::Logger *logger = Log4Qt::Logger::rootLogger();
Log4Qt::TTCCLayout *layout = new Log4Qt::TTCCLayout();
layout->setName("My Layout");
layout->activateOptions();
// 创建一个 RollingFileAppender
QString file = QCoreApplication::applicationDirPath() + "/debug.log";
Log4Qt::RollingFileAppender *appender = new Log4Qt::RollingFileAppender(layout, file, true);
appender->setName("My Appender");
appender->setMaximumFileSize(10 * 1024); // 文件的最大大小为 10 KB
appender->setMaxBackupIndex(5); // 最大文件数为 5 个
appender->activateOptions();
// 在 logger 上添加 appender
logger->addAppender(appender);
// 设置级别为 DEBUG
logger->setLevel(Log4Qt::Level::DEBUG_INT);
// 读取文件,并写入日志
QFile f("E:/Backup.log");
if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&f);
QString line;
while (!in.atEnd()) {
line = in.readLine();
logger->debug(line);
}
f.close();
}
// 关闭 logger
logger->removeAllAppenders();
logger->loggerRepository()->shutdown();
return a.exec();
}