内容简介:AppenderSkeleton继承自Appender类,实现了Appender的通用功能,但没有实现继承自Appender的部分接口,所以仍然是一个抽象类,不能实例化。AppenderSkeleton的所有函数都是线程安全的。自定义Appender可以从AppenderSkeleton派生,须要实现以下三个接口:append接口负责处理LoggingEvent对象,将格式化的日志信息输出到不同的输出地,如文本流、文件流、数据库等,如果需要将日志信息重定向到QWidget组件,需要在append函数发送信
Log4Qt快速入门——Log4Qt日志输出重定向源码解析
一、Appender简介
1、Appender简介
Appender是所有Appender的抽象类,是对记录日志形式的抽象。Log4Qt(Qt4版本)中Appender继承体系如下:
2、Appender接口
virtual Filter *filter() const = 0; virtual QString name() const = 0; virtual Layout *layout() const = 0; virtual bool requiresLayout() const = 0; virtual void setLayout(Layout *pLayout) = 0; virtual void setName(const QString &rName) = 0; virtual void addFilter(Filter *pFilter) = 0; virtual void clearFilters() = 0; virtual void close() = 0; virtual void doAppend(const LoggingEvent &rEvent) = 0;
二、AppenderSkeleton
1、AppenderSkeleton简介
AppenderSkeleton继承自Appender类,实现了Appender的通用功能,但没有实现继承自Appender的部分接口,所以仍然是一个抽象类,不能实例化。AppenderSkeleton的所有函数都是线程安全的。
2、AppenderSkeleton接口
virtual Filter *filter() const; virtual Layout *layout() const; bool isActive() const; bool isClosed() const; virtual QString name() const; Level threshold() const; virtual void setLayout(Layout *pLayout); virtual void setName(const QString &rName); void setThreshold(Level level); virtual void activateOptions(); virtual void addFilter(Filter *pFilter); virtual void clearFilters(); virtual void close(); virtual void doAppend(const LoggingEvent &rEvent); Filter* firstFilter() const; bool isAsSevereAsThreshold(Level level) const;
自定义Appender可以从AppenderSkeleton派生,须要实现以下三个接口:
virtual void append(const LoggingEvent &rEvent) = 0; virtual bool requiresLayout() const = 0; virtual QDebug debug(QDebug &rDebug) const = 0;
append接口负责处理LoggingEvent对象,将格式化的日志信息输出到不同的输出地,如文本流、文件流、数据库等,如果需要将日志信息重定向到QWidget组件,需要在append函数发送信号,日志信息作为信号参数,在相应的QWidget组件的槽函数接收处理日志信息。
也可以根据需要从WriterAppender、ConsoleAppender、
FileAppender、RollingFileAppender、DailyRollingFileAppender派生类进行实现。
三、WriterAppender
1、WriterAppender简介
WriterAppender类继承自AppenderSkeleton类,在其实现的append函数中会将LoggingEvent对象的日志信息输出到QTextStream对象。WriterAppender的所有函数是线程安全的。
void WriterAppender::append(const LoggingEvent &rEvent) { QString message(layout()->format(rEvent)); //输出格式化的日志信息到QTextStream对象 *mpWriter << message; if (handleIoErrors()) return; // 是否刷新 if (immediateFlush()) { mpWriter->flush(); if (handleIoErrors()) return; } }
2、WriterAppender常用接口
QTextCodec *encoding() const;
获取输出文本流的编码器
bool immediateFlush() const;
获取是否立即刷新
QTextStream *writer() const;
获取输出文本流对象
void setEncoding(QTextCodec *pTextCodec);
设置文本流的编码器
void setImmediateFlush(bool immediateFlush);
设置是否立即刷新
void setWriter(QTextStream *pTextStream);
设置输出文本流
virtual void close();
关闭文本流,如果有设置页脚,会打印出页脚信息
四、ConsoleAppender
1、ConsoleAppender简介
ConsoleAppender类继承自WriterAppender类,ConsoleAppender定义了标准输出、标准错误两种控制台的输出目的地。ConsoleAppender的所有函数是线程安全的。
enum Target { STDOUT_TARGET,//标准输出 STDERR_TARGET//标准错误 };
2、ConsoleAppender日志重定向的实现
在ConsoleAppender配置完成后,需要对其配置选项进行激活,ConsoleAppender的activateOptions函数中会将文本流指向相应控制台的文本流对象。
void ConsoleAppender::activateOptions() { QMutexLocker locker(&mObjectGuard); closeStream(); if (mTarget == STDOUT_TARGET) mpTextStream = new QTextStream(stdout); else mpTextStream = new QTextStream(stderr); // 调用WriterAppender的setWriter函数, // 将日志信息重定向到控制台对应的文本流 setWriter(mpTextStream); WriterAppender::activateOptions(); }
当Logger进行日志输出时,会在WriterAppender的append函数将格式化的日志信息输出到相应控制台对应的文本流,完成输出目的地的重定向。
3、ConsoleAppender常用接口
QString target() const;
获取输出目的地
void setTarget(const QString &rTarget);
设置rTarget字符串为输出目的地
void setTarget(Target target);
设置target为输出目的地
virtual void activateOptions();
激活ConsoleAppender设置的选项
virtual void close();
关闭ConsoleAppender
4、ConsoleAppender示例
#include <QCoreApplication> #include <QTextCodec> #include <log4qt/logger.h> #include <log4qt/ttcclayout.h> #include <log4qt/consoleappender.h> #include <log4qt/loggerrepository.h> #include <QThread> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QThread::currentThread()->setObjectName("MainThread"); // 创建TTCCLayout Log4Qt::Logger *logger = Log4Qt::Logger::rootLogger(); Log4Qt::TTCCLayout *layout = new Log4Qt::TTCCLayout(); layout->setDateFormat("yyyy-mm-dd hh:mm:ss"); // 激活选项 layout->activateOptions(); // 创建ConsoleAppender Log4Qt::ConsoleAppender *appender = new Log4Qt::ConsoleAppender(); appender->setLayout(layout); // 设置编码 appender->setEncoding(QTextCodec::codecForName("UTF-8")); // 设置输出目的地为stdout appender->setTarget(Log4Qt::ConsoleAppender::STDOUT_TARGET); appender->setImmediateFlush(true); // 设置阈值级别为INFO appender->setThreshold(Log4Qt::Level::INFO_INT); // 激活选项 appender->activateOptions(); logger->addAppender(appender); // 设置级别为 DEBUG logger->setLevel(Log4Qt::Level::DEBUG_INT); // 输出信息 logger->debug("你好, Log4Qt!"); logger->info("你好, Qt!"); // 关闭 logger logger->removeAllAppenders(); logger->loggerRepository()->shutdown(); return a.exec(); } // output: // 2018-03-12 18:03:48 [MainThread] INFO root - 你好, Qt!
五、FileAppender
1、FileAppender简介
FileAppender类继承自WriterAppender类,用于将日志输出到文件。
FileAppender的所有函数是线程安全的。
2、FileAppender日志重定向的实现
在FileAppender配置完成后,需要对其配置选项进行激活,FileAppender的activateOptions函数中会打开指定的输出文件,并将WriterAppender的文本流绑定到输出文件的文件流,实现将WriterAppender的文本流重定向到输出文件中。
void FileAppender::activateOptions() { QMutexLocker locker(&mObjectGuard); if (mFileName.isEmpty()) { LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of Appender '%1' that requires file and has no file set"), APPENDER_ACTIVATE_MISSING_FILE_ERROR); e << name(); logger()->error(e); return; } closeFile(); // 打开文件 openFile(); WriterAppender::activateOptions(); } void FileAppender::openFile() { Q_ASSERT_X(mpFile == 0 && mpTextStream == 0, "FileAppender::openFile()", "Opening file without closing previous file"); QFileInfo file_info(mFileName); QDir parent_dir = file_info.dir(); if (!parent_dir.exists()) { logger()->trace("Creating missing parent directory for file %1", mFileName); QString name = parent_dir.dirName(); parent_dir.cdUp(); parent_dir.mkdir(name); } mpFile = new QFile(mFileName); QFile::OpenMode mode = QIODevice::WriteOnly | QIODevice::Text; //配置文件流的写入模式 if (mAppendFile) mode |= QIODevice::Append; else mode |= QIODevice::Truncate; if (!mBufferedIo) mode |= QIODevice::Unbuffered; if (!mpFile->open(mode)) { LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to open file '%1' for appender '%2'"), APPENDER_OPENING_FILE_ERROR); e << mFileName << name(); e.addCausingError(LogError(mpFile->errorString(), mpFile->error())); logger()->error(e); return; } // 将文件流绑定文本流 mpTextStream = new QTextStream(mpFile); // 将WriterAppender的文本流重定向到文本文件的文件流对应的文本流 // 完成输出目的地的重定向 setWriter(mpTextStream); logger()->debug("Opened file '%1' for appender '%2'", mpFile->fileName(), name()); }
当Logger进行日志输出时,会在WriterAppender的append函数将格式化的日志信息输出到文本流绑定的输出文件中,完成输出目的地的重定向。
3、FileAppender接口
bool appendFile() const;
获取是否追加文件
QString file() const;
获取输出目的地的文件名
bool bufferedIo() const;
获取是否为缓存IO
void setAppendFile(bool append);
设置是否为追加文件
void setBufferedIo(bool buffered);
设置是否为缓存IO
void setFile(const QString &rFileName);
设置输出目的地的文件名
virtual void close();
关闭文件
4、FileAppender示例
#include <QCoreApplication> #include <QTextCodec> #include <log4qt/logger.h> #include <log4qt/ttcclayout.h> #include <log4qt/fileappender.h>.h> #include <log4qt/loggerrepository.h> #include <QThread> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QThread::currentThread()->setObjectName("MainThread"); // 创建TTCCLayout Log4Qt::Logger *logger = Log4Qt::Logger::rootLogger(); Log4Qt::TTCCLayout *layout = new Log4Qt::TTCCLayout(); layout->setDateFormat("yyyy-mm-dd hh:mm:ss"); // 激活选项 layout->activateOptions(); // 创建ConsoleAppender Log4Qt::FileAppender *appender = new Log4Qt::FileAppender; // 设置输出目的地为应用程序所在目录下的logFile.log appender->setFile("logFile.log"); appender->setLayout(layout); // 设置编码 appender->setEncoding(QTextCodec::codecForName("UTF-8")); appender->setImmediateFlush(true); // 设置阈值级别为INFO appender->setThreshold(Log4Qt::Level::INFO_INT); // 激活选项 appender->activateOptions(); logger->addAppender(appender); // 设置级别为 DEBUG logger->setLevel(Log4Qt::Level::DEBUG_INT); // 输出信息 logger->debug("你好, Log4Qt!"); logger->info("你好, Qt!"); // 关闭 logger logger->removeAllAppenders(); logger->loggerRepository()->shutdown(); return a.exec(); } // logFile: // 2018-06-12 18:06:45 [MainThread] INFO root - 你好, Qt!
六、RollingFileAppender
1、RollingFileAppender简介
RollingFileAppender类继承自FileAppender类,是对FileAppender功能的扩展。RollingFileAppender允许输出的日志文件达到指定大小时进行日志文件的滚动备份。
RollingFileAppender的所有函数都是线程安全的。
2、RollingFileAppender日志重定向的实现
在RollingFileAppender配置完成后,需要对其配置选项进行激活,RollingFileAppender调用FileAppender::activateOptions函数中会中会打开指定的输出文件,并将WriterAppender的文本流绑定到输出文件的文件流,实现将WriterAppender的文本流重定向到输出文件中。
RollingFileAppender实现了append函数。
void RollingFileAppender::append(const LoggingEvent &rEvent) { // Q_ASSERT_X(, "RollingFileAppender::append()", "Lock must be held by caller") // 使用FileAppender将输出文件绑定到WidgetAppender的输出文本流 FileAppender::append(rEvent); // 如果日志文件大小已经大于日志文件指定的最大值,进行会滚备份操作 if (writer()->device()->size() > this->mMaximumFileSize) rollOver(); }
当Logger进行日志输出时,RollingFileAppender使用FileAppender::append(实际为WriterAppender::append)函数将将格式化的日志信息输出到文本流绑定的输出文件中,完成输出目的地的重定向。如果输出文件的大小大于指定的最大值时,进行会滚备份操作。
3、RollingFileAppender接口
int maxBackupIndex() const;
获取最大备份索引
qint64 maximumFileSize() const;
获取输出日志文件大小的最大值
void setMaxBackupIndex(int maxBackupIndex);
设置备份文件索引的最大值
void setMaximumFileSize(qint64 maximumFileSize);
设置单个输出日志文件的最大值为maximumFileSize字节
void setMaxFileSize(const QString &rMaxFileSize);
设置单个输出日志文件的最大值为rMaxFileSize的值,可以使用KB,MB,GB等单位
4、RollingFileAppender示例
#include <QCoreApplication> #include <QTextCodec> #include <log4qt/logger.h> #include <log4qt/ttcclayout.h> #include <log4qt/rollingfileappender.h>.h>.h> #include <log4qt/loggerrepository.h> #include <QThread> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QThread::currentThread()->setObjectName("MainThread"); // 创建TTCCLayout Log4Qt::Logger *logger = Log4Qt::Logger::rootLogger(); Log4Qt::TTCCLayout *layout = new Log4Qt::TTCCLayout(); layout->setDateFormat("yyyy-mm-dd hh:mm:ss"); // 激活选项 layout->activateOptions(); // 创建ConsoleAppender Log4Qt::RollingFileAppender *appender = new Log4Qt::RollingFileAppender; // 设置输出目的地为应用程序所在目录下的logFile.log appender->setFile("logFile.log"); // 设置日志为追加方式写入输出文件 appender->setAppendFile(true); // 设置备份文件的最大数量为10个 appender->setMaxBackupIndex(10); // 设置输出文件的最大值为1KB appender->setMaxFileSize("1KB"); appender->setLayout(layout); // 设置编码 appender->setEncoding(QTextCodec::codecForName("UTF-8")); appender->setImmediateFlush(true); // 设置阈值级别为INFO appender->setThreshold(Log4Qt::Level::INFO_INT); // 激活选项 appender->activateOptions(); logger->addAppender(appender); // 设置级别为 DEBUG logger->setLevel(Log4Qt::Level::DEBUG_INT); // 输出信息 for(int i = 0 ; i < 100; i++) { logger->debug("你好, Log4Qt!"); logger->info("你好, Qt!"); } // 关闭 logger logger->removeAllAppenders(); logger->loggerRepository()->shutdown(); return a.exec(); }
程序最近的日志输出到logFile.log,并备份有5个文件,分别为logFile.log.1、logFile.log.2、logFile.log.3、logFile.log.4、logFile.log.5
七、DailyRollingFileAppender
1、DailyRollingFileAppender简介
DailyRollingFileAppender类继承自FileAppender类,是对FileAppender功能的扩展。DailyRollingFileAppender允许输出的日志文件按照指定的频率进行会滚备份。
DailyRollingFileAppender的所有函数都是线程安全的。
DailyRollingFileAppender定义了六种日期模式。
enum DatePattern { MINUTELY_ROLLOVER = 0,// 每分钟,'yyyy-MM-dd-hh-mm" HOURLY_ROLLOVER,// 每小时,yyyy-MM-dd-hh HALFDAILY_ROLLOVER,// 每半天,yyyy-MM-dd-a DAILY_ROLLOVER,// 每天,yyyy-MM-dd WEEKLY_ROLLOVER,// 每周,yyyy-ww MONTHLY_ROLLOVER// 每月,yyyy-MM };
2、DailyRollingFileAppender日志重定向的实现
在DailyRollingFileAppender配置完成后,需要对其配置选项进行激活,DailyRollingFileAppender的activateOptions函数中会计算输出文件回滚的频率,并调用FileAppender::activateOptions()函数将WriterAppender的文本流绑定到输出文件的文件流,实现将WriterAppender的文本流重定向到输出文件中。
void DailyRollingFileAppender::activateOptions() { QMutexLocker locker(&mObjectGuard); // 计算输出文件回滚的频率, computeFrequency(); if (!mActiveDatePattern.isEmpty()) { //计算输出文件回滚的时间 computeRollOverTime(); // 调用FileAppender::activateOptions重定向输出文本流到输出文件 FileAppender::activateOptions(); } }
DailyRollingFileAppender实现了append函数。
void DailyRollingFileAppender::append(const LoggingEvent &rEvent) { // 如果当前时间大于输出文件回滚时间,进行输出文件回滚 if (QDateTime::currentDateTime() > mRollOverTime) rollOver(); // 调用FileAppender::append将格式化的日志输出到输文件 FileAppender::append(rEvent); }
当Logger进行日志输出时,DailyRollingFileAppender会在append函数内处理LoggingEvent对象。如果当前时间大于输出文件需要进行回滚的时间,DailyRollingFileAppender会进行输出文件的回滚备份操作,创建新的日志输出文件。然后调用FileAppender::append函数将格式化的日志输出到指定的输出文件中。
3、DailyRollingFileAppender接口
QString datePattern() const;
获取日期匹配模式字符串
void setDatePattern(DatePattern datePattern);
设置日期匹配模式
void setDatePattern(const QString &rDatePattern);
设置rDatePattern为日期匹配模式
4、DailyRollingFileAppender示例
#include <QCoreApplication> #include <QTextCodec> #include <log4qt/logger.h> #include <log4qt/ttcclayout.h> #include <log4qt/dailyrollingfileappender.h>> #include <log4qt/loggerrepository.h> #include <QThread> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QThread::currentThread()->setObjectName("MainThread"); // 创建TTCCLayout Log4Qt::Logger *logger = Log4Qt::Logger::rootLogger(); Log4Qt::TTCCLayout *layout = new Log4Qt::TTCCLayout(); layout->setDateFormat("yyyy-mm-dd hh:mm:ss"); // 激活选项 layout->activateOptions(); // 创建ConsoleAppender Log4Qt::DailyRollingFileAppender *appender = new Log4Qt::DailyRollingFileAppender; // 设置输出目的地为应用程序所在目录下的logFile.log appender->setFile("logFile.log"); // 设置日志文件每天回滚 //appender->setDatePattern(Log4Qt::DailyRollingFileAppender::MINUTELY_ROLLOVER); appender->setDatePattern("'.'yyyy-MM-dd-hh-mm"); // 设置日志为追加方式写入输出文件 appender->setAppendFile(true); appender->setLayout(layout); // 设置编码 appender->setEncoding(QTextCodec::codecForName("UTF-8")); appender->setImmediateFlush(true); // 设置阈值级别为INFO appender->setThreshold(Log4Qt::Level::INFO_INT); // 激活选项 appender->activateOptions(); logger->addAppender(appender); // 设置级别为 DEBUG logger->setLevel(Log4Qt::Level::DEBUG_INT); // 输出信息 for(int i = 0; i < 10; i++) { logger->debug("你好, Log4Qt!"); logger->info("你好, Qt!"); for(int i = 0; i < 1000000000; i++) ; logger->debug("你好, Log4Qt2!"); logger->info("你好, Qt2!"); } // 关闭 logger logger->removeAllAppenders(); logger->loggerRepository()->shutdown(); return a.exec(); }
程序执行时,日志输出到logFile.log,输出日志每分钟会回滚备份一次,备份文件名称如下:logFile.log.2018-10-12-18-30。
八、重定向日志到QWidget
1、Log4Qt源码导入
将Log4Qt源码工程下的src/log4qt目录拷贝到自己的工程中,并在自己的工程文件中添加如下配置:
# 定义所需的宏 DEFINES += LOG4QT_LIBRARY # 将Log4Qt源码工程下的src/log4qt目录拷贝到自己的工程src目录中 # 定义Log4Qt源码根目录 LOG4QT_ROOT_PATH = $$PWD/log4qt # 指定编译项目时应该被搜索的#include目录 INCLUDEPATH += $$LOG4QT_ROOT_PATH # 将Log4Qt源代码添加至项目中 include($$LOG4QT_ROOT_PATH/log4qt.pri)
2、WidgetAppender实现
WidgetAppender从AppenderSkeleton进行实现。
WidgetAppender.h文件:
#ifndef WIDGETAPPENDER_H #define WIDGETAPPENDER_H #include <QObject> #include <QWidget> #include "appenderskeleton.h" #include <QDebug> namespace Log4Qt { /** * @brief WidgetAppender继承自AppenderSkeleton类,用于将日志信息重定向到QWidget组件 * @author scorpio * @note WidgetAppender的使用注意事项: * 1、必须使用setLogWidget接口设置日志信息的重定向位置,即输出窗口组件 * 2、必须实现一个槽函数onAppendLog(const QString& msg),用于接收WidgetAppender * 发送的logAppend(const QString& msg)信号,参数msg即接收的日志信息,输出窗口组件 * 需要将msg输出到相应窗体。 */ class WidgetAppender : public AppenderSkeleton { Q_OBJECT public: WidgetAppender(QObject *parent = NULL); ~WidgetAppender(); /** * @brief 设置日志信息输出的QWidget组件 * @param widget,输入参数,日志信息输出窗口,需要开发者自己实现 */ void setLogWidget(const QWidget& widget); signals: /** * @brief 新增加一条日志信息的信号 * @param msg,输入参数,格式化后的日志信息 * @note logAppend信号由QWidget输出窗口组件接收,开发者需要在输出窗口组件实现 * 槽函数onAppendLog(const QString& msg)。 */ void logAppend(const QString& msg); protected: virtual bool requiresLayout() const; virtual void append(const Log4Qt::LoggingEvent &rEvent); #ifndef QT_NO_DEBUG_STREAM virtual QDebug debug(QDebug &rDebug) const; #endif //QT_NO_DEBUG_STREAM private: QWidget *m_logWidget; }; } #endif // WIDGETAPPENDER_H
WidgetAppender.cpp文件:
#include "WidgetAppender.h" #include "loggingevent.h" #include <log4qt/ttcclayout.h> namespace Log4Qt { WidgetAppender::WidgetAppender(QObject *parent): AppenderSkeleton(parent) { m_logWidget = NULL; } WidgetAppender::~WidgetAppender() { } void WidgetAppender::setLogWidget(const QWidget &widget) { m_logWidget = const_cast<QWidget*>(&widget); //连接槽函数到输出窗口的onAppendLog(const QString&)槽函数 connect(this, SIGNAL(logAppend(const QString&)), m_logWidget, SLOT(onAppendLog(const QString&))); } bool WidgetAppender::requiresLayout() const { return true; } void WidgetAppender::append(const LoggingEvent &rEvent) { // 格式化日志信息 QString message = dynamic_cast<TTCCLayout*>(layout())->format(rEvent); emit logAppend(message); } #ifndef QT_NO_DEBUG_STREAM QDebug WidgetAppender::debug(QDebug &rDebug) const { return rDebug.space(); } #endif //QT_NO_DEBUG_STREAM }
3、QWidget输出窗口实现
Widget.h文件:
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QTextEdit> #include <QMutex> #include <QVBoxLayout> class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = 0); ~Widget(); private slots: /** * @brief 接收日志信息的槽函数 * @param log,输入参数,格式化后的日志信息 */ void onAppendLog(const QString& log); private: QTextEdit* m_logEdit; QMutex m_mutex; }; #endif // WIDGET_H
Widget.cpp文件:
#include "Widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) { m_logEdit = new QTextEdit(); QVBoxLayout* layout = new QVBoxLayout; layout->addWidget(m_logEdit); setLayout(layout); resize(600, 400); } Widget::~Widget() { } void Widget::onAppendLog(const QString &log) { QMutexLocker lock(&m_mutex); //将日志信息输出到窗口组件 m_logEdit->insertPlainText(log); }
4、应用示例
#include "Widget.h" #include <QApplication> #include <log4qt/basicconfigurator.h> #include <log4qt/logger.h> #include <log4qt/WidgetAppender.h> #include <log4qt/ttcclayout.h> #include <log4qt/logmanager.h> int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); Log4Qt::BasicConfigurator::configure(); Log4Qt::LogManager::setHandleQtMessages(true); Log4Qt::Logger *logger = Log4Qt::Logger::rootLogger(); logger->removeAllAppenders(); Log4Qt::WidgetAppender *appender = new Log4Qt::WidgetAppender(); appender->setName("WidgetAppender"); Log4Qt::TTCCLayout *layout = new Log4Qt::TTCCLayout(Log4Qt::TTCCLayout::ISO8601); layout->setThreadPrinting(true); appender->setLayout(layout); appender->activateOptions(); //设置日志信息输出的窗口组件 appender->setLogWidget(w); logger->addAppender(appender); logger->warn("hello Log4Qt"); logger->info("hello Log4Qt"); logger->debug("hello Log4Qt"); logger->info("你好 Log4Qt"); logger->removeAllAppenders(); return a.exec(); } // output: // 2018-10-09 10:27:18.542 [] WARN root - hello Log4Qt // 2018-10-09 10:27:18.542 [] INFO root - hello Log4Qt // 2018-10-09 10:27:18.542 [] DEBUG root - hello Log4Qt // 2018-10-09 10:27:18.542 [] INFO root - 你好 Log4Qt
以上所述就是小编给大家介绍的《Log4Qt快速入门——Log4Qt日志输出重定向源码解析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Mybatis 源码入门
- 从源码分析 MySQL 死锁问题入门
- 兄弟连区块链入门教程以太坊源码分析hashimoto源码分析(一)
- Spring入门进阶之DispatcherServlet源码分析
- Jetpack系列 - Lifecycle从入门到源码
- 兄弟连区块链入门教程以太坊源码分析core-vm源码分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web前端开发最佳实践
党建 / 机械工业出版社 / 2015-1 / 59.00元
本书贴近Web前端标准来介绍前端开发相关最佳实践,目的在于让前端开发工程师提高编写代码的质量,重视代码的可维护性和执行性能,让初级工程师从入门开始就养成一个良好的编码习惯。本书总共分五个部分13章,第一部分包括第1章和第2章,介绍前端开发的基本范畴和现状,并综合介绍前端开发的一些最佳实践;第二部分为第3-5章,讲解HTML相关的最佳实践,并简单介绍HTML5中新标签的使用;第三部分为第6-8章,介......一起来看看 《Web前端开发最佳实践》 这本书的介绍吧!