介绍
Log4Qt是使用Trolltech Qt Framework的Apache Software Foundation Log4j包的C ++端口。它旨在供开源和商业Qt项目使用。所以 Log4Qt 是Apache Log4J 的Qt移植版,所以看Log4J的资料应该是最直接有效的(因为 Log4Qt的直接资料太少了)。
Log4Qt主要是用来记录日志(有助于程序调试)。有3个主要的组件:
1、Logger
提供日志记录服务,可以有多个Logger存在,每个有它们自己的名字。Logger间存在隶属关系,有一个Logger称为根Logger。
2、Appender
用来指明将日志记录到什么地方:比如,控制台、文件、数据库,等等
3、Layout
控制日志的输出格式,可以类比一下C中的printf哈。
下载log4qt源码
源码下载
当前最新版本为log4qt-0.3.zip,这源码包最后修改日期为2009年3月1日。
Sourceforge 下载地址:
https://sourceforge.net/projects/log4qt/
或者
https://github.com/devbean/log4qt
或者
https://gitee.com/mirrors/log4qt
编译为动态库
使用qtCreater打开pro文件:文件路径:qt_log\log4qt\tests\log4qttest.pro
Qt4版本日志移植到qt5编译过程出现错误
错误一:识别QtMsgHandler类
“error: 'QtMsgHandler' does not name a type”
错误二:QObject类未声明
点击跳转到错误文件,添加QObject
错误三:QTextCodec编码错误
错误四:操作符“<<”歧义
错误五:qInstallMsgHandle未声明
错误六:Qt编译错误: 'UnicodeUTF8' is not a member of 'QApplication'
错误七:error: undefined reference to `vtable for
原因:
子类没有实现父类的纯虚函数;在Qt中,首先要想到的是在一个类中添加了新的继承QObject,并添加了 Q_OBJECT 宏,然后执行构造或重新构造,都会造成这个错误。根本原因是,只执行构造或重新构造,都不会编译新添加的宏Q_OBJECT。因此在这之前要执行qmake让moc编译器去预编译Q_OBJECT然后再执行构造,就不再报错了。
项目使用
pro文件中添加
#log start
LIBS +=-LD:\C++\plugins\dll/ -lhlog4qt1
INCLUDEPATH +=D:\C++\plugins\include
#log end
main.cpp
/* 根据指定的日志配置文件初始化日志 */
Log4Qt::PropertyConfigurator::configure( "./mylog.conf");
Log4Qt::Logger *mylog1 = Log4Qt::Logger::logger("Mylog1");
/* 处理qt调试输出信息,将qDebug之类的信息重定向到日志文件 */
Log4Qt::LogManager::setHandleQtMessages(true);
/* 日志输出 */
mylog1->debug("log debug");
mylog1->info("log info");
mylog1->warn("log warn");
mylog1->error("log error");
mylog1->fatal("log fatal");
qDebug("qDebug");
qInfo("qInfo");
qWarning("qWarning");
qCritical("qCritical");
qFatal("qCritical");
qDebug()<<"qDebug()";
QT自带日志库
#include <QMutex>
#include <QMutexLocker>
#include <QFile>
#include <QTextStream>
#include <QMessageLogContext>
class SaveLog
{
public:
static SaveLog* Instance()
{
static SaveLog instance;
return &instance;
}
bool getUseContext() const { return useContext; }
void setUseContext(bool value) { useContext = value; }
void save(const QString &log)
{
// 将日志内容保存到文件
QFile file("log.txt");
if (file.open(QIODevice::Append)) {
QTextStream out(&file);
out << log << "\n";
file.close();
}
}
private:
SaveLog() : useContext(true) {}
bool useContext;
};
// 日志处理函数
void Log(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
static QMutex mutex;
QMutexLocker locker(&mutex);
QString content;
switch (type) {
case QtDebugMsg:
case QtInfoMsg:
content = QString("Debug/Info: %1").arg(msg);
break;
case QtWarningMsg:
content = QString("Warning: %1").arg(msg);
break;
case QtCriticalMsg:
content = QString("Critical: %1").arg(msg);
break;
case QtFatalMsg:
content = QString("Fatal: %1").arg(msg);
break;
}
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
if (SaveLog::Instance()->getUseContext() && context.line != -1) {
content = QString("%1 (%2, %3, %4)")
.arg(content)
.arg(context.file)
.arg(context.line)
.arg(context.function);
}
#endif
SaveLog::Instance()->save(content);
}
// 安装日志钩子
void start()
{
qInstallMessageHandler(Log);
}
// 卸载日志钩子
void stop()
{
qInstallMessageHandler(nullptr);
}
使用
start();
qDebug()<<"hehe";
qInfo()<<"你好";
qWarning()<<"finish";
qCritical()<<"critical";
// qFatal("fatal");
qDebug()<<"ttt";
stop();