Log4Qt 日志格式化(PatternLayout)

源码共读

共 7704字,需浏览 16分钟

 ·

2021-10-21 03:09

👇👇关注后回复 “进群” ,拉你进程序员交流群👇👇

作者丨Waleon

来源丨高效程序员



1

继承关系图


Log4Qt 提供了各种布局对象,通过使用这些 Layout,我们可以根据自己的喜好来格式化日志输出,自由指定日志级别、线程名称、Logger 名称、日期时间等信息。


Log4Qt::Layout 继承关系图:



在该层次结构中,顶级类是 Layout,它是 Log4Qt API 中所有其他布局类的基类。


  • PatternLayout:根据一个模式字符串输出日志事件

  • SimpleLayout:输出日志事件的级别和消息

  • TTCCLayout:输出日志事件的时间、线程名称、Logger 名称和嵌套的诊断上下文信息


注意:这里列出来的这几个 Layout 比较常用,也是我们重点讲解的内容。此外,还有一些其它 Layout(例如:BinaryLayoutXMLLayout 等),这里并没有列出,希望通过后面分享的知识,大家能够快速熟悉它们的用法。


这些类扩展了 Layout,并根据提供的模式重写了 format() 方法来构造日志信息。


在内部,PatternLayoutTTCCLayout 通过 PatternFormatter 来实现格式化。当 PatternFormatter 解析模式字符串时,它会根据发现的信息创建了一个 PatternConverter 链,每个 PatternConverter 会处理 LoggingEvent 的某个成员。



2

转换字符




转换字符:用于指定数据的类型,例如:类别、级别、日期、线程名称。




转换说明符以百分号(%)开始,后跟转换字符。Log4Qt 中的转换字符有:


转换字符 含义
c{section_count} Logger 名称。参数 section_count 可选,从 logger 名称的末尾处计数,分隔符是“::”
d{format_string} 日期。参数 format_string 可选,被用于 QDateTime::toString()
m 消息
p 级别名称
r 启动应用程序的相对日期/时间
t 线程名称
x NDC(嵌套的诊断上下文)名称
X MDC(映射的诊断上下文)名称
F 文件名称
M 方法名称
L 行号
l 位置信息
n 平台相关的行分隔符(Windows:\r\n,Linux:\n)
% 序列 %% 输出一个百分号 %



3

PatternLayout


如果想生成基于模式的特定格式的日志信息,那么可以使用 PatternLayout 来进行格式化。


枚举 ConversionPattern 定义了两个常用的模式:


枚举 模式字符串
DEFAULT_CONVERSION_PATTERN “%m,%n”
TTCC_CONVERSION_PATTERN “%r [%t] %p %c %x - %m%n”



基本使用


创建一个 PatternLayout,并将日志信息输出至控制台中:


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

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

    // 创建一个 PatternLayout(根据模式字符串输出日志事件)
    Log4Qt::Logger *logger = Log4Qt::Logger::rootLogger();
    Log4Qt::PatternLayout *layout = new Log4Qt::PatternLayout();
    layout->setHeader("----- Header -----");  // 设置标头信息
    layout->setFooter("----- Footer -----");  // 设置页脚信息
    layout->setName("My Layout");
    // layout->setConversionPattern(Log4Qt::PatternLayout::TTCC_CONVERSION_PATTERN);
    // layout->setConversionPattern("%d{yyyy-MM-dd hh:mm:ss} - %m%n");
    // layout->setConversionPattern("The output message is: %m%n");
    layout->activateOptions();

    // 创建一个 ConsoleAppender(将日志内容输出到控制台上)
    Log4Qt::ConsoleAppender *appender = new Log4Qt::ConsoleAppender(layout, Log4Qt::ConsoleAppender::STDOUT_TARGET);
    appender->setName("My Appender");
    appender->activateOptions();
    logger->addAppender(appender);

    logger->setLevel(Log4Qt::Level::DEBUG_INT);
    logger->debug("Hello, Log4Qt!");

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

    return a.exec();
}

注意:除正文之外,还可以为日志消息指定标头和页脚。布局对象的内容类型默认为 text/plain,如果要自定义布局并制定其他类型,需要重写 Layout 的 contentType() 方法。


默认情况下,转换模式为 DEFAULT_CONVERSION_PATTERN,只会输出简单的日志信息:

----- Header -----

Hello, Log4Qt!

----- Footer -----

由于我们在代码中指定了标头和页脚,所以在日志信息的前后会输出相关信息,这有时在区分日志时会很有用。



指定转换模式


和其他布局相比,PatternLayout 很大的一个优势在于灵活。除了上述方式之外,还可以指定其它模式。


若要修改默认模式,可以打开代码中的注释部分:


layout->setConversionPattern(Log4Qt::PatternLayout::TTCC_CONVERSION_PATTERN);


运行程序,这时不仅会输出日志信息,还会输出启动时间、线程名称、logger 名称:

4 [0x000001bdc8415750] DEBUG root  - Hello, Log4Qt!

实际上,这采用的是和 TTCCLayout 相同的模式,从名字就可以看出。


此外,还可以通过自定义模式字符串来指定日期时间:


layout->setConversionPattern("%d{yyyy-MM-dd hh:mm:ss} - %m%n");


运行程序,输出如下:

2021-08-17 22:54:04 - Hello, Log4Qt!

如果想额外为消息添加一些文本,也非常简单:


layout->setConversionPattern("The output message is: %m%n");


运行程序,输出如下:

The output message is: Hello, Log4Qt!

通过这种方式,我们可以自由地在转换模式中插入任何文本,使用起来相当方便。



使用配置文件


出于灵活性考虑,在以后的使用中,配置文件将是我们的首选,所以务必要学会如何有效地利用它。


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


# 定义 rootLogger
log4j.rootLogger=DEBUG, console

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

# 为 ConsoleAppender 定义 Layout
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.header=----- Header -----
log4j.appender.console.layout.footer=----- Footer -----
log4j.appender.console.layout.conversionPattern=%r [%t] %p %c %x - %m%n

然后,使用下面的程序:

#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!");

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

    return a.exec();
}

注意:最后记得关闭 logger,否则不会释放资源,也不会输出 Footer。


运行程序,输出如下:

----- Header -----

65 [0x000001d25ec81f70] DEBUG root  - Hello, Log4Qt!

----- Footer -----

可以看出,使用配置文件和纯代码的效果是一样的。

-End-

最近有一些小伙伴,让我帮忙找一些 面试题 资料,于是我翻遍了收藏的 5T 资料后,汇总整理出来,可以说是程序员面试必备!所有资料都整理到网盘了,欢迎下载!

点击👆卡片,关注后回复【面试题】即可获取

在看点这里好文分享给更多人↓↓

浏览 24
点赞
评论
收藏
分享

手机扫一扫分享

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

手机扫一扫分享

分享
举报