Log4Qt 中的 rootLogger、logLogger、qtLogger
来源:互联网 发布:ubuntu 16.04 mongodb 编辑:程序博客网 时间:2024/05/18 23:13
简述
使用 Log4Qt 时,你会发现有一系列的 Logger - rootLogger、logLogger、qtLogger。。。蒙圈,有木有?简直傻傻分不清楚!
Why?这么多 Logger,它们到底有什么关系?均适用于哪种场景?
- 简述
- 相互关系
- 关系链
- 等价调用
- 验证
- 适用场景
- logLogger
- qtLogger
版权所有:一去丶二三里,转载请注明出处:http://blog.csdn.net/liang19890820
相互关系
要了解它们之间的关系,最直接的方法就是从源码着手 - 源码面前,了无秘密!
关系链
从 Logger 类开始,查看相关源码:
Logger *Logger::rootLogger(){ return LogManager::rootLogger();}Logger *Logger::logger(const QString &rName){ return LogManager::logger(rName);}
可以看到,它们在内部调用的是 LogManager 类的相关接口:
Logger *LogManager::rootLogger(){ return instance()->mpLoggerRepository->rootLogger();}Logger *LogManager::logger(const QString &rName){ return instance()->mpLoggerRepository->logger(rName);}inline Logger *LogManager::logLogger(){ return logger(QLatin1String("Log4Qt"));}inline Logger *LogManager::qtLogger(){ return logger(QLatin1String("Qt"));}
而这些最终都是由 Hierarchy 类来决定:
inline Logger *Hierarchy::rootLogger() const{ // QReadLocker locker(&mObjectGuard); // Constant for object lifetime return mpRootLogger;}Logger *Hierarchy::logger(const QString &rName){ QWriteLocker locker(&mObjectGuard); return createLogger(rName);}
由于 rootLogger() 返回的是 mpRootLogger,根据 Hierarchy 的构造函数:
Hierarchy::Hierarchy() : mObjectGuard(QReadWriteLock::Recursive), mLoggers(), mThreshold(Level::NULL_INT), mpRootLogger(logger(QString())){ // Store root logger to allow rootLogger() to be const}
可以发现,mpRootLogger 最终也是调用了 Hierarchy::logger(const QString &rName)
,只不过传递的是一个空字符串而已。
到这里,可以很直观地得到这样一个调用关系:
Logger::rootLogger() -> LogManager::rootLogger() -> Hierarchy::logger(QString())
LogManager::logLogger() -> LogManager::logger("Log4Qt") -> Hierarchy::logger("Log4Qt")
LogManager::qtLogger() -> LogManager::logger("Qt") -> Hierarchy::logger("Qt")
等价调用
通过上述调用关系,最终定位 Hierarchy::logger(const QString &rName)
,而它内部则调用了 Hierarchy::createLogger(const QString &orgName)
:
Logger *Hierarchy::createLogger(const QString &orgName){ static const char binaryIndicator[] = "@@binary@@"; QString rName(OptionConverter::classNameJavaToCpp(orgName)); bool needBinaryLogger = orgName.contains(binaryIndicator); if (needBinaryLogger) rName.remove(binaryIndicator); const QString name_separator = QLatin1String("::"); Logger *p_logger = mLoggers.value(rName, nullptr); if (p_logger != nullptr) return p_logger; if (rName.isEmpty()) { p_logger = new Logger(this, Level::DEBUG_INT, QLatin1String("root"), nullptr); mLoggers.insert(QString(), p_logger); return p_logger; } QString parent_name; int index = rName.lastIndexOf(name_separator); if (index >= 0) parent_name = rName.left(index); if (needBinaryLogger) p_logger = new BinaryLogger(this, Level::NULL_INT, rName, createLogger(parent_name)); else p_logger = new Logger(this, Level::NULL_INT, rName, createLogger(parent_name)); mLoggers.insert(rName, p_logger); return p_logger;}
根据源码可知,Logger 的创建是由形参 rName 的值来决定的:
- 空字符串:用于创建 rootLogger,其 name 被设置为了“root”,而 mLoggers(QHash 类型)中对应的 key 为 QString()。
- 非空字符串:用于创建其他 Logger(包括:logLogger、qtLogger),并将其 parentLogger 设置为 rootLogger(注意构造时的递归调用
createLogger(parent_name)
)。
所以,最终得出以下结论:
rootLogger()
:等价于logger(QString())
,其name()
和objectName()
都是“root”。logLogger()
:等价于logger(“Log4Qt”)
,其name()
和objectName()
都是“Log4Qt”。qtLogger()
:等价于logger(“Qt”)
,其name()
和objectName()
都是“Qt”。- rootLogger 是根 Logger,而其他 Logger(包括:logLogger、qtLogger)的 parentLogger 是 rootLogger。
验证
实践出真知,求证一下吧!
对各个 Logger 分类,并进行输出:
#include <QCoreApplication>#include <qDebug>#include <log4qt/basicconfigurator.h>#include <log4qt/logger.h>#include <log4qt/logmanager.h>int main(int argc, char *argv[]){ QCoreApplication a(argc, argv); // 一个简单的基础配置 Log4Qt::BasicConfigurator::configure(); // 获取 rootLogger Log4Qt::Logger *rootLogger = Log4Qt::Logger::rootLogger(); Log4Qt::Logger *rootLogger2 = Log4Qt::LogManager::rootLogger(); Log4Qt::Logger *rootLogger3 = Log4Qt::Logger::logger(""); Log4Qt::Logger *rootLogger4 = Log4Qt::LogManager::logger(""); Log4Qt::Logger *rootParentLogger = rootLogger->parentLogger(); qDebug() << "********** rootLogger **********"; qDebug() << rootLogger << rootLogger2 << rootLogger3 << rootLogger4; qDebug() << "name:" << rootLogger->name() << "object name:" << rootLogger->objectName(); qDebug() << "parent logger:" << rootParentLogger; // 获取 logLogger Log4Qt::Logger *logLogger = Log4Qt::LogManager::logLogger(); Log4Qt::Logger *logLogger2 = Log4Qt::Logger::logger("Log4Qt"); Log4Qt::Logger *logLogger3 = Log4Qt::LogManager::logger("Log4Qt"); Log4Qt::Logger *logParentLogger = logLogger->parentLogger(); qDebug() << "********** logLogger **********"; qDebug() << logLogger << logLogger2 << logLogger3; qDebug() << "name:" << logLogger->name() << "object name:" << logLogger->objectName(); qDebug() << "parent logger:" << logParentLogger; // 获取 qtLogger Log4Qt::Logger *qtLogger = Log4Qt::LogManager::qtLogger(); Log4Qt::Logger *qtLogger2 = Log4Qt::Logger::logger("Qt"); Log4Qt::Logger *qtLogger3 = Log4Qt::LogManager::logger("Qt"); Log4Qt::Logger *qtParentLogger = qtLogger->parentLogger(); qDebug() << "********** qtLogger **********"; qDebug() << qtLogger << qtLogger2 << qtLogger3; qDebug() << "name:" << qtLogger->name() << "object name:" << qtLogger->objectName(); qDebug() << "parent logger:" << qtParentLogger; return a.exec();}
显然,和推断一样。。。通过各种方式获取到的 Logger 其实都是等价的,而且一直存在一个 rootLogger,它是所有 Logger 的 parentLogger。
适用场景
rootLogger 是根,而 logLogger、qtLogger 是基于特定的需求而诞生的,下面重点讲解 qtLogger。
logLogger
logLogger:用于记录内部消息的 logger
也就是说,Log4Qt 除了对外提供日志之外,它内部也用了自己的日志(即:logLogger)来记录消息。关于包内记录,官方有一个简单说明 - Logging within the package。
既然是内部操作,这部分就不做过多赘述了,了解即可。
qtLogger
qtLogger:用于记录由 qDebug()、qWarning()、qCritical() 和 qFatal() 所创建的消息。
默认情况下,这些消息处理是禁用的。可以通过调用 setHandleQtMessages(true)
来启用。一旦启用,所有的消息都将使用 qtLogger() 来记录。
下面,将日志消息输出到文件中:
除了使用 rootLogger 之外,我们额外再使用 qDebug()
输出一条消息:
#include <QCoreApplication>#include <QtDebug>#include <log4qt/logger.h>#include <log4qt/logmanager.h>#include <log4qt/ttcclayout.h>#include <log4qt/fileappender.h>#include <log4qt/loggerrepository.h>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(将日志内容输出到文件中) // true 以 Append 方式打开文件,false 以 Truncate 方式打开文件。 QString file = QCoreApplication::applicationDirPath() + "/debug.log"; Log4Qt::FileAppender *appender = new Log4Qt::FileAppender(layout, file, true); appender->setName("My Appender"); appender->activateOptions(); // 在 rootLogger 上添加 fileAppender logger->addAppender(appender); // 设置级别为 DEBUG logger->setLevel(Log4Qt::Level::DEBUG_INT); // 允许处理 Qt 消息 Log4Qt::LogManager::setHandleQtMessages(true); // 输出信息 logger->debug("This is a debug message."); qDebug() << "This is a debug message too."; // 关闭 rootLogger logger->removeAllAppenders(); logger->loggerRepository()->shutdown(); return a.exec();}
运行程序,然后打开 debug.log 文件。可以看到,使用 qDebug()
生成的消息也被输出到文件里了。
- Log4Qt 中的 rootLogger、logLogger、qtLogger
- log4qt Qt中的配置
- 获取 Log4Qt 中的 logger
- Log4Qt
- Log4Qt
- log4j.rootLogger
- log4j.rootLogger 是配置
- Log4j rootLogger配置
- Log4Qt 使用笔记(一)
- Log4Qt 使用笔记(二)
- Log4Qt使用笔记(三)
- Log4Qt使用笔记(三)
- log4qt使用示例
- log4qt的使用
- log4qt -- for Qt5 使用说明
- log4qt的使用
- Log4Qt 使用笔记(一)
- log4qt 使用(一)
- C初识数组
- 牛顿法、指数分布
- 文章标题
- Android Volley完全解析(一),初识Volley的基本用法
- [架构师之路] 数据库拆分 系列(上)
- Log4Qt 中的 rootLogger、logLogger、qtLogger
- 人工智能时代关于平板发展的建议
- Zookeeper系列—ZooInspector 连接不到 Zookeeper的解决方法
- TextView实现走马灯效果
- 使用TCP协议编写一个网络程序,设置服务器端的监听端口是8002,当与客户端建立连接后,服务器端向客户端发送数据“Hello, world”,客户端收到数据后打印输出。
- BAT脚本编写教程(比较易懂和全面)
- [架构师之路] 数据库拆分 系列(下)
- 《android framework常用api源码分析》之系统app启动安装流程
- 数论——逆元