Log4Qt 日志格式化(TTCCLayout)
作者丨Waleon
來源丨高效程序員
1
TTCC 概要
SimpleLayout 對(duì)象采用的格式化風(fēng)格非常簡單,在某些情況下可能比較有用,但有時(shí)我們希望得到更詳細(xì)的信息,特別是在多線程應(yīng)用程序中。當(dāng)多個(gè)客戶端訪問同一應(yīng)用程序模塊時(shí),發(fā)布日志記錄的時(shí)間、活動(dòng)線程等信息非常重要,可以以此來區(qū)分多個(gè)獨(dú)立的客戶端行為。
TTCCLayout 負(fù)責(zé)提供有關(guān)日志事件的詳細(xì)信息,通常它包含以下內(nèi)容:
Time:從啟動(dòng)應(yīng)用程序開始,以毫秒數(shù)計(jì)算的時(shí)間;Thread:調(diào)用線程;Category:用于創(chuàng)建日志事件的類別或 Logger;Context:NDC 信息。此信息不會(huì)自動(dòng)包含在LoggingEvent對(duì)象中,必須專門包含它。因此,這是TTCCLayout的一個(gè)可選輸出 - 即使啟用了 NDC 設(shè)置,如果LoggingEvent不包含任何 NDC 設(shè)置,TTCCLayout也可能不會(huì)顯示任何 NDC 數(shù)據(jù)。
注意:TTCC 正是這些單詞的縮寫組合,因此而得名。
此外,這幾個(gè)字段中的每一個(gè)都可以單獨(dú)啟用或禁用(可選參數(shù),并不強(qiáng)制)。
對(duì)于 TTCCLayout 來說,可以決定是否啟用上面的可選參數(shù)。然而,即使不啟用它們,也仍將輸出以下信息:
Level:日志消息的級(jí)別;Message:日志消息本身;
換句話說,這兩個(gè)是強(qiáng)制性信息,不受可選參數(shù)的影響!
日期格式,取決于 DateFormat:
| 枚舉 | 日期格式字符串 | 將被格式化為 |
|---|---|---|
| NONE | "NONE" | |
| ISO8601 | "ISO8601" | yyyy-MM-dd hh:mm:ss.zzz |
| ABSOLUTE | "ABSOLUTE" | HH:mm:ss.zzz |
| DATE | "DATE" | MMM YYYY HH:mm:ss.zzzz |
| RELATIVE | "RELATIVE" | 自程序啟動(dòng)以來經(jīng)過的時(shí)間(以毫秒為單位) |
其中,RELATIVE 是默認(rèn)值。
TTCCLayout 由好幾部分組成,而最終各個(gè)部分能否出現(xiàn)在日志中,取決于它們是否作為 LoggingEvent 的一部分被提供到 TTCCLayout。
通過下表中列出的屬性或方法,TTCCLayout 可以靈活地控制日志消息的不同部分:
| 屬性 | 方法 | 描述 | 默認(rèn)值 |
|---|---|---|---|
| categoryPrefixing | setCategoryPrefixing(bool) | 指定 Logger 名稱是否是格式化輸出的一部分 | true |
| contextPrinting | setContextPrinting(bool) | 指定嵌套的上下文信息是否是格式化輸出的一部分 | true |
| threadPrinting | setThreadPrinting(bool) | 指定線程名稱是否是格式化輸出的一部分 | true |
| dateFormat | setDateFormat(const QString &) | 指定布局使用的日期格式 | "RELATIVE" |
有了這些知識(shí),編寫一個(gè) TTCCLayout 的相關(guān)程序會(huì)簡單很多。為了完整起見,我們首先會(huì)以編程方式配置 TTCCLayout,隨后再通過配置文件進(jìn)行配置。
2
以編程方式配置
要在程序中配置日志,首先要獲得一個(gè) Logger 實(shí)例,然后將 ConsoleAppender 附加到這個(gè)實(shí)例上。為了格式化日志消息,我們還將創(chuàng)建一個(gè) TTCCLayout 對(duì)象,并將其附加到 ConsoleAppender 中。
和前面一樣,輸出一個(gè)簡單的信息:
#include <QCoreApplication>
#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);
// 創(chuàng)建一個(gè) TTCCLayout(輸出時(shí)間、線程、Logger 以及消息內(nèi)容)
Log4Qt::Logger *logger = Log4Qt::Logger::rootLogger();
Log4Qt::TTCCLayout *layout = new Log4Qt::TTCCLayout();
layout->setName("My Layout");
// layout->setCategoryPrefixing(false); // 禁用 logger 名稱
// layout->setContextPrinting(false); // 禁用嵌套的上下文信息
// layout->setThreadPrinting(false); // 禁用線程名
// layout->setDateFormat("ISO8601"); // 設(shè)置日期格式
layout->activateOptions();
// 創(chuàng)建一個(gè) ConsoleAppender(將日志內(nèi)容輸出到控制臺(tái)上)
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!");
// 關(guān)閉 logger
logger->removeAllAppenders();
logger->loggerRepository()->shutdown();
return a.exec();
}
注意:可以通過注釋部分,對(duì)可選屬性進(jìn)行靈活控制。
運(yùn)行此程序,將在控制臺(tái)中生成以下輸出:
170 [0x000002ab780c14e0] DEBUG root - Hello, Log4Qt!
打開注釋部分,再次運(yùn)行程序,輸出如下:
2021-09-16 22:57:44.243 DEBUG - Hello, Log4Qt!
可以看到,日期格式變了,并且 Logger、線程也被禁用了。
3
使用配置文件
現(xiàn)在,編寫一個(gè)配置文件 - log4qt.properties,執(zhí)行與上例中使用相同的任務(wù):
# 定義 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.TTCCLayout
log4j.appender.console.layout.categoryPrefixing=false
log4j.appender.console.layout.contextPrinting=false
log4j.appender.console.layout.threadPrinting=false
log4j.appender.console.layout.dateFormat=ISO8601
在此配置中,我們禁用了 categoryPrefixing、contextPrinting、以及 threadPrinting 屬性,并為 dateFormat 指定了一個(gè)時(shí)間格式 ISO8601。
然后,使用下面的程序:
#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!");
// 關(guān)閉 rootLogger
logger->removeAllAppenders();
logger->loggerRepository()->shutdown();
return a.exec();
}
運(yùn)行此程序,將在控制臺(tái)中生成以下輸出:
2021-09-16 23:01:41.409 DEBUG - Hello, Log4Qt!
可以看到,無論是使用編程方式,還是配置文件方式,效果是一樣的。
-End-
最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

面試題】即可獲取