Log4Qt 輸出重定向(控制臺(tái))
作者丨Waleon
來(lái)源丨高效程序員
1
繼承關(guān)系
Log4Qt 支持自定義輸出,格式化由 Layout 完成,輸出地則由 Appender 控制。Appender 表示將日志輸出到什么地方,常見的 Appender 有控制臺(tái)、文件、數(shù)據(jù)庫(kù)等。
Log4Qt::Appender 繼承關(guān)系圖:

在該層次結(jié)構(gòu)中,頂級(jí)類是 Appender,它是 Log4Qt API 中所有其他輸出地的基類。
AppenderSkeleton:實(shí)現(xiàn)一般Appender的功能通常來(lái)講,自定義輸出需要繼承
AppenderSkeleton,并實(shí)現(xiàn)其中的幾個(gè)方法。TelnetAppender:將日志事件附加到只讀套接字(telnet)SignalAppender:在附加日志事件的同時(shí),會(huì)發(fā)射一個(gè)appended(const QString &)信號(hào)。DatabaseAppender:將日志事件附加到數(shù)據(jù)庫(kù)WriterAppender:將日志事件附加到QTextStreamDailyFileAppender:每天創(chuàng)建一個(gè)日志文件RollingFileAppender:在達(dá)到特定大小時(shí)滾動(dòng)日志文件DailyRollingFileAppender:以指定的頻率滾動(dòng)日志文件ConsoleAppender:將日志事件附加到stdout或stderrFileAppender:將日志事件附加到文件
注意:除了這些之外,還有其他的一些 Appender,這里就不再列出了。
2
Logger-to-Appender 協(xié)作
目前為止,我們已經(jīng)了解了 Logger 對(duì)象如何封裝日志信息,以及不同的 Appender 對(duì)象如何將日志信息打印到不同的目的地。但是 Logger 對(duì)象是如何將日志信息傳遞給 Appender 對(duì)象的呢?創(chuàng)建一個(gè)名為 LoggingEvent 的中間鏈接對(duì)象可以實(shí)現(xiàn)這一點(diǎn)。
LoggingEvent類封裝了所有相關(guān)的日志信息,例如:Logger實(shí)例、日志消息、日志級(jí)別、時(shí)間戳等。在將日志請(qǐng)求移交給任何關(guān)聯(lián)的
Appender之前,Logger會(huì)使用與日志記錄相關(guān)的信息創(chuàng)建LoggingEvent對(duì)象的實(shí)例。然后,
Logger對(duì)象調(diào)用Appender對(duì)象的doAppend(LoggingEvent event)方法。doAppend()方法對(duì)日志請(qǐng)求執(zhí)行一些關(guān)鍵的檢查,例如:將請(qǐng)求的日志級(jí)別與Logger相關(guān)聯(lián)的任何Appender的閾值級(jí)別進(jìn)行比較,檢查Appender是否打開,并使用Appender檢查任何關(guān)聯(lián)的Filter對(duì)象。如果找到
Filter對(duì)象,它將調(diào)用該Filter對(duì)象以進(jìn)一步?jīng)Q定日志記錄請(qǐng)求。一旦批準(zhǔn),相關(guān)子類Appender對(duì)象的append()方法將接管并發(fā)布日志記錄信息。
3
ConsoleAppender
ConsoleAppender 是一個(gè)非常簡(jiǎn)單的類,用于將日志信息輸出到 stdout 或 stderr,可以通過(guò)名為 target 的屬性來(lái)配置日志消息的目的地。該類擴(kuò)展了 WriterAppender,任何打算將日志信息打印到控制臺(tái)的應(yīng)用程序都應(yīng)該使用它。
下表描述了 ConsoleAppender 的可配置屬性以及對(duì)應(yīng)的方法:
| 屬性 | 方法 | 描述 |
|---|---|---|
| immediateFlush | setImmediateFlush(bool) | 默認(rèn)情況下,該標(biāo)志被設(shè)置為 true,這將導(dǎo)致控制臺(tái)流在每個(gè)日志輸出請(qǐng)求中被刷新。 |
| threshold | setThreshold(Level) | Appender 使用的閾值級(jí)別,任何低于閾值的日志請(qǐng)求都將被忽略。 |
| target | setTarget(const QString &) | 輸出目標(biāo),默認(rèn)是 STDOUT_TARGET。 |
其中,targer 的枚舉及字符串(不區(qū)分大小寫)表示:
enum Target
{
/*! The output target is standard out. */
STDOUT_TARGET,
/*! The output target is standard error. */
STDERR_TARGET
};
Q_ENUM(Target)
注意:threshold 是由 AppenderSkeleton 提供的,而 immediateFlush 則來(lái)自于 WriterAppender。
4
以編程方式配置
在項(xiàng)目開發(fā)階段,往往需要在控制臺(tái)中輸出日志的內(nèi)容,這對(duì)于調(diào)試代碼來(lái)說(shuō)非常方便。這時(shí),便可以很好的利用 ConsoleAppender:

和前面一樣,輸出一個(gè)簡(jiǎn)單的信息:
#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);
// 創(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->activateOptions();
// 創(chuàng)建一個(gè) ConsoleAppender(將日志內(nèi)容輸出到控制臺(tái)上)
Log4Qt::ConsoleAppender *appender = new Log4Qt::ConsoleAppender();
appender->setName("My Appender");
appender->setLayout(layout);
appender->setEncoding(QTextCodec::codecForName("UTF-8")); // 設(shè)置編碼
appender->setTarget(Log4Qt::ConsoleAppender::STDOUT_TARGET); // 輸出到 stdout
appender->setImmediateFlush(true); // 立即刷新
appender->setThreshold(Log4Qt::Level::INFO_INT); // 設(shè)置閾值級(jí)別為 INFO
appender->activateOptions();
// 在 logger 上添加 appender
logger->addAppender(appender);
// 設(shè)置級(jí)別為 DEBUG
logger->setLevel(Log4Qt::Level::DEBUG_INT);
// 輸出信息
logger->debug("Hello, Log4Qt!");
logger->info("Hello, Qt!");
// 關(guān)閉 logger
logger->removeAllAppenders();
logger->loggerRepository()->shutdown();
return a.exec();
}
這里,我們將 ConsoleAppender 的閾值級(jí)別設(shè)置為 INFO,當(dāng)打印信息時(shí),只有 level >= INFO 的信息才會(huì)被輸出。所以,最終的輸出是“Hello, Qt!”,而沒(méi)有輸出“Hello, Log4Qt!”。
5
使用配置文件
現(xiàn)在,編寫一個(gè)配置文件 - log4qt.properties,執(zhí)行與上例中相同的任務(wù):
# 定義 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!");
// 關(guān)閉 rootLogger
logger->removeAllAppenders();
logger->loggerRepository()->shutdown();
return a.exec();
}
-End-
最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來(lái),可以說(shuō)是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

面試題】即可獲取
