Log4Qt 输出重定向(控制台)

高效程序员

共 5917字,需浏览 12分钟

 ·

2021-10-13 10:43

星标/置顶 公众号👇硬核文章第一时间送达


1

继承关系


Log4Qt 支持自定义输出,格式化由 Layout 完成,输出地则由 Appender 控制。Appender 表示将日志输出到什么地方,常见的 Appender 有控制台、文件、数据库等。


Log4Qt::Appender 继承关系图:



在该层次结构中,顶级类是 Appender,它是 Log4Qt API 中所有其他输出地的基类。


  • AppenderSkeleton:实现一般 Appender 的功能

    通常来讲,自定义输出需要继承 AppenderSkeleton,并实现其中的几个方法。

  • TelnetAppender:将日志事件附加到只读套接字(telnet)

  • SignalAppender:在附加日志事件的同时,会发射一个 appended(const QString &) 信号。

  • DatabaseAppender:将日志事件附加到数据库

  • WriterAppender:将日志事件附加到 QTextStream

    • DailyFileAppender:每天创建一个日志文件

    • RollingFileAppender:在达到特定大小时滚动日志文件

    • DailyRollingFileAppender:以指定的频率滚动日志文件

    • ConsoleAppender:将日志事件附加到 stdoutstderr

    • FileAppender:将日志事件附加到文件


注意:除了这些之外,还有其他的一些 Appender,这里就不再列出了。



2

Logger-to-Appender 协作


目前为止,我们已经了解了 Logger 对象如何封装日志信息,以及不同的 Appender 对象如何将日志信息打印到不同的目的地。但是 Logger 对象是如何将日志信息传递给 Appender 对象的呢?创建一个名为 LoggingEvent 的中间链接对象可以实现这一点。


  1. LoggingEvent 类封装了所有相关的日志信息,例如:Logger 实例、日志消息、日志级别、时间戳等。

  2. 在将日志请求移交给任何关联的 Appender 之前,Logger 会使用与日志记录相关的信息创建 LoggingEvent 对象的实例。

  3. 然后,Logger 对象调用 Appender 对象的 doAppend(LoggingEvent event) 方法。

  4. doAppend() 方法对日志请求执行一些关键的检查,例如:将请求的日志级别与 Logger 相关联的任何 Appender 的阈值级别进行比较,检查 Appender 是否打开,并使用 Appender 检查任何关联的 Filter 对象。

  5. 如果找到 Filter 对象,它将调用该 Filter 对象以进一步决定日志记录请求。一旦批准,相关子类 Appender 对象的 append() 方法将接管并发布日志记录信息。



3

ConsoleAppender


ConsoleAppender 是一个非常简单的类,用于将日志信息输出到 stdoutstderr,可以通过名为 target 的属性来配置日志消息的目的地。该类扩展了 WriterAppender,任何打算将日志信息打印到控制台的应用程序都应该使用它。



可配置属性


下表描述了 ConsoleAppender 的可配置属性以及对应的方法:


属性方法描述
immediateFlushsetImmediateFlush(bool)默认情况下,该标志被设置为 true,这将导致控制台流在每个日志输出请求中被刷新。
thresholdsetThreshold(Level)Appender 使用的阈值级别,任何低于阈值的日志请求都将被忽略。
targetsetTarget(const QString &)输出目标,默认是 STDOUT_TARGET。


其中,targer 的枚举及字符串(不区分大小写)表示:


enum Target
{
    /*! The output target is standard out. */
    STDOUT_TARGET,
    /*! The output target is standard error. */
    STDERR_TARGET
};
Q_ENUM(Target)


注意:threshold 是由 AppenderSkeleton 提供的,而 immediateFlush 则来自于 WriterAppender



4

以编程方式配置


在项目开发阶段,往往需要在控制台中输出日志的内容,这对于调试代码来说非常方便。这时,便可以很好的利用 ConsoleAppender



和前面一样,输出一个简单的信息:


#include <QCoreApplication>
#include <QTextCodec>
#include <log4qt/logger.h>
#include <log4qt/ttcclayout.h>
#include <log4qt/consoleappender.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();

    // 创建一个 ConsoleAppender(将日志内容输出到控制台上)
    Log4Qt::ConsoleAppender *appender = new Log4Qt::ConsoleAppender();
    appender->setName("My Appender");
    appender->setLayout(layout);
    appender->setEncoding(QTextCodec::codecForName("UTF-8"));  // 设置编码
    appender->setTarget(Log4Qt::ConsoleAppender::STDOUT_TARGET);  // 输出到 stdout
    appender->setImmediateFlush(true);  // 立即刷新
    appender->setThreshold(Log4Qt::Level::INFO_INT);  // 设置阈值级别为 INFO
    appender->activateOptions();

    // 在 logger 上添加 appender
    logger->addAppender(appender);

    // 设置级别为 DEBUG
    logger->setLevel(Log4Qt::Level::DEBUG_INT);

    // 输出信息
    logger->debug("Hello, Log4Qt!");
    logger->info("Hello, Qt!");

    // 关闭 logger
    logger->removeAllAppenders();
    logger->loggerRepository()->shutdown();

    return a.exec();
}


这里,我们将 ConsoleAppender 的阈值级别设置为 INFO,当打印信息时,只有 level >= INFO 的信息才会被输出。所以,最终的输出是“Hello, Qt!”,而没有输出“Hello, Log4Qt!”。



5

使用配置文件


现在,编写一个配置文件 - log4qt.properties,执行与上例中相同的任务:


# 定义 rootLogger
log4j.rootLogger=DEBUG, console

# 定义 ConsoleAppender
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.target=STDOUT_TARGET
log4j.appender.console.immediateFlush=true
log4j.appender.console.threshold=INFO

# 为 ConsoleAppender 定义 Layout
log4j.appender.console.layout=org.apache.log4j.TTCCLayout

然后,使用下面的程序:

#include <QCoreApplication>
#include <log4qt/logger.h>
#include <log4qt/loggerrepository.h>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 获取 rootLogger
    Log4Qt::Logger* logger = Log4Qt::Logger::rootLogger();

    // 打印消息
    logger->debug("Hello, Log4Qt!");
    logger->info("Hello, Qt!");

    // 关闭 rootLogger
    logger->removeAllAppenders();
    logger->loggerRepository()->shutdown();

    return a.exec();
}

运行程序,结果和上面的效果相同(效果图不再展示,请自行尝试)。



往期推荐




☞ 专辑 | 趣味设计模式
☞ 专辑 | 音视频开发
☞ 专辑 | C++ 进阶
☞ 专辑 | 超硬核 Qt
☞ 专辑 | 玩转 Linux
☞ 专辑 | GitHub 开源推荐
☞ 专辑 | 程序人生


关注公众「高效程序员」👇一起优秀!

回复 “入群” 进技术交流群,回复 “1024” 获取海量学习资源。
浏览 22
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报