目录
- Qt日志输出及QsLog日志库
- 日志输出
- 格式化日志
- 普通格式化
- 条件格式化
- 环境变量设置格式化
- 日志输出位置
- 日志输出对象信息
- 禁用输出
- QsLog日志库
- 使用方法
- 1. 将QsLog目录添加到项目中
- 2. 配置CMakeLists.txt文件
- 3. 配置.pro文件
- 4. 日志记录器的配置
- 5. 运行程序
- 6. 启用行号和文件名
- CMakeLists.txt
- .pro 文件
- 7. 禁用日志输出
- CMakeLists.txt
- .pro 文件
Qt日志输出及QsLog日志库
日志输出
Qt提供了多种方式进行日志输出,常用的有qDebug()
, qInfo()
, qWarning()
, qCritical()
和qFatal()
。
这些输出函数定义在#include <QDebug>
中,并且可以像标准C++的输出流一样使用。
分类 | 说明 |
---|---|
qDebug() | 用于调试信息输出,通常用于开发阶段输出调试信息。 |
qInfo() | 用于一般的信息输出,适合输出一般运行状态信息。 |
qWarning() | 用于警告信息输出,通常用于提示可能的问题。 |
qCritical() | 用于严重错误信息输出,通常用于提示不可恢复的错误。 |
qFatal() | 用于致命错误信息输出,通常会中止程序的运行。 |
C风格输出
qDebug("我是%s,今年%d岁了~","qDebug",20);
qInfo("老铁%d",666);
qWarning("hello %s","warning");
qCritical("helo %s","critical");
qFatal("hello %s","qFatal"); // 注意:qFatal 会中断程序执行
C++风格
qDebug()<<"qDebug";
qInfo()<<"qInfo";
qWarning()<<"qWarnning";
qCritical()<<"qCritical";
#qFatal()<<"qFatal"; // qFatal()不能用"<<"输出
格式化日志
默认情况下,日志格式是只输出对应的日志内容没有额外信息的。可以通过修改环境变量QT_MESSAGE_PATTERN
或者调用方法 qSetMessagePattern
来修改日志的输出格式。日志格式中常用的占位符号如下所示:
%{appname} 应用程序的名称(QCoreApplication::applicationName())
%{category} 日志所处的领域
%{file} 打印该日志的文件路径
%{function} 打印日志的函数
%{line} 打印日志在文件中的行数
%{message} 日志的内容
%{pid} 打印日志的程序的PID(QCoreApplication::applicationPid())
%{threadid} 打印日志的线程ID
%{qthreadptr} 打印日志的线程指针
%{type} 日志级别("debug", "warning", "critical" or "fatal")
%{time process}日志发生时程序启动了多久
%{time boot} 日志发生时系统启动了多久
%{time [format]}以固定时间格式输出日志打印的时间,默认为QISODate格式
普通格式化
格式化日志方法如下:
#include <QApplication>
#include <QDebug>int main(int argc, char *argv[])
{QApplication a(argc, argv);qSetMessagePattern("%{time yyyy-MM-dd hh:mm:ss} [%{type}] %{file} [%{function}(%{line})] %{message}");qInfo()<<"info";qDebug()<<"debug";qWarning()<<"warning";qCritical()<<"Critical";return a.exec();
}
输出的日志内容如下:
2024-09-19 10:35:25 [info] ..\..\main.cpp [qMain(9)] info
2024-09-19 10:35:25 [debug] ..\..\main.cpp [qMain(10)] debug
2024-09-19 10:35:25 [warning] ..\..\main.cpp [qMain(11)] warning
2024-09-19 10:35:25 [critical] ..\..\main.cpp [qMain(12)] Critical
注意:在Release模式下,文件名、函数名、行号获取不到,需要添加编译时宏QT_MESSAGELOGCONTEXT
条件格式化
在消息参数中还可以使用条件,给不同级别的日志指定不同的格式,语法如下:
%{if-<debug | info | warning | critical | fatal>} ... %{endif}
比如,只想在debug级别下输出文件名、函数名以及行号,代码格式如下:
qSetMessagePattern("%{time yyyy-MM-dd hh:mm:ss} [%{type}] %{if-debug}%{file}%{endif} %{if-} [%{function}(%{line})] %{message}");
环境变量设置格式化
格式也可以在运行时通过设置QT_MESSAGE_PATTERN
环境变量来更改;
如果调用了qSetMessagePattern()
并且设置了QT_MESSAGE_PATTERN
,则环境变量优先。
qputenv("QT_MESSAGE_PATTERN", QByteArray("%{time yyyy-MM-dd hh:mm:ss} [%{type}] %{file} [%{function}(%{line})] %{message}"));
日志输出位置
Qt 默认的日志内容是输出到终端的,不会输出到文件里面,如果需要将日志内容输出到文件中,需要通过qInstallMessageHandler
设置日志信息处理函数。使用方法如下:
#include <QApplication>
#include <QFile>
#include <QDebug>
#include <QTextStream>// 日志消息的处理函数
void logMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message)
{// 获取格式化的日志信息QString typeStr = qFormatLogMessage(type, context, message);// 可以根据日志的级别进行过滤(比如不想要 Debug 输出,可以直接 return)QString levelText;switch (type){case QtDebugMsg:levelText = "Debug";// return; // 加上 return 之后就不会打印 debug 日志了break;case QtInfoMsg:levelText = "Info";break;case QtWarningMsg:levelText = "Warning";break;case QtCriticalMsg:levelText = "Critical";break;case QtFatalMsg:levelText = "Fatal";break;}QFile file("log.log");file.open(QIODevice::WriteOnly | QIODevice::Append);QTextStream textStream(&file);textStream << typeStr << "\n";
}int main(int argc, char *argv[])
{QCoreApplication app(argc, argv);qSetMessagePattern("%{time yyyy-MM-dd hh:mm:ss} [%{type}]%{if-warning}[%{function}]%{endif}%{if-fatal}[%{function}--%{line}]%{endif}:%{message}");qInstallMessageHandler(logMessageHandler);qDebug() << "debug info occurred";qInfo() << "call other function";qWarning() << "doesn't work";qFatal("fatal error");return app.exec();
}
如果需要关闭日志输出,取消之前注册的日志处理函数,可以调用qInstallMessageHandler(nullptr);
日志输出对象信息
在调试一些复杂对象的时候,需要输出对象的成员信息到日志当中。但是默认情况下 Qt 的日志库是不支持输出自定义对象的。这时候可以通过重写操作符实现对自定义对象的日志输出。使用方法如下:
class Person
{
public:QString name;quint8 age;inline friend QDebug operator<<(QDebug debug,const Person& person){debug<<"Person("<<person.name<<","<<person.age<<")";return debug;}
};int main(int argc,char*argv[])
{QCoreApplication app(argc, argv);Person person{"shayebushi",18}; // 输出:Person( "shayebushi" , 18 )qDebug()<<person;return app.exec();
}
禁用输出
在开发或者调试时,我们必须借助日志来进行判断,但是当程序需要发布时,调试的日志信息将不再需要,此时如果把代码删除,又不太方便,万一出bug了,又需要调试了呢?
所以Qt提供了禁用qInfo
、qWarning
、qDebug
输出的宏,qCritical
、qFatal
是错误不能屏蔽!
CMakeLists.txt 文件中禁用日志输出
在CMakeLists.txt文件中添加如下三行,即可禁用qInfo
、qWarning
、qDebug
的输出。
add_compile_definitions(QT_NO_INFO_OUTPUT)
add_compile_definitions(QT_NO_DEBUG_OUTPUT)
add_compile_definitions(QT_NO_WARNING_OUTPUT)
#或
add_compile_definitions(QT_NO_INFO_OUTPUTQT_NO_DEBUG_OUTPUTQT_NO_WARNING_OUTPUT)
.pro 文件中禁用日志输出
在 .pro 文件中添加如下三行,即可禁用 qInfo
、qWarning
、qDebug
的输出。
DEFINES += QT_NO_INFO_OUTPUT
DEFINES += QT_NO_DEBUG_OUTPUT
DEFINES += QT_NO_WARNING_OUTPUT
QsLog日志库
QsLog是一个基于Qt的QDebug类的易于使用的记录器。QsLog是在MIT许可下以开源形式发布的。
QsLog Github下载
QsLog的特征:
- 六个日志级别(从跟踪到致命);
- 运行时可配置的日志级别阈值;
- 关闭日志记录时的最小开销;
- 支持多个目标,附带文件和调试目标;
- 线程安全;
- 支持现成的常见Qt类型的日志记录;
- 小依赖:直接把它放到你的项目中。
使用方法
1. 将QsLog目录添加到项目中
将QsLog目录直接拷贝到项目的根目录中,与CMakeLists.txt
或.pro
文件同级。
2. 配置CMakeLists.txt文件
打开项目的CMakeLists.txt
文件,输入如下代码:
# 添加子目录
add_subdirectory(./QsLog)# 添加可执行文件
add_executable(QsLog_test main.cpp)# 把QsLog库链接到目标 QsLog_test
target_link_libraries(QsLog_test Qt${QT_VERSION_MAJOR}::Core QsLog)
3. 配置.pro文件
如果你使用的是qmake构建系统,打开项目的.pro
文件,输入如下代码:
# 指定包含QsLog目录
include(QsLog/QsLog.pri)
4. 日志记录器的配置
在你的代码中进行日志记录器的配置:
#include <QCoreApplication>
#include "QsLog/QsLog.h"
#include "QsLog/QsLogDest.h"int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);using namespace QsLogging;// 1. 获取日志单例Logger &logger = Logger::instance();logger.setLoggingLevel(QsLogging::DebugLevel);// 2. 添加两个日志输出目的地DestinationPtr file_dest(DestinationFactory::MakeFileDestination("log.txt"));DestinationPtr console_dest(DestinationFactory::MakeDebugOutputDestination());logger.addDestination(file_dest);logger.addDestination(console_dest);// 3. 开始日志记录QLOG_DEBUG() << "Program started";return a.exec();
}
5. 运行程序
运行程序,控制台会输出日志,同时指定的文件也会记录日志内容。日志内容如下:
DEBUG 2024-09-19T18:07:04.434 Program started
6. 启用行号和文件名
输出的日志记录默认是没有文件名和行号的,如果需要,在CMakeLists.txt
或.pro
文件中添加宏定义即可。
CMakeLists.txt
# 开启行号
add_compile_definitions(QS_LOG_LINE_NUMBERS)
.pro 文件
# 开启行号
DEFINES += QS_LOG_LINE_NUMBERS
7. 禁用日志输出
如果要禁用日志输出,定义宏 QS_LOG_DISABLE
即可。
CMakeLists.txt
# 禁用日志输出
add_compile_definitions(QS_LOG_DISABLE)
.pro 文件
# 禁用日志输出
DEFINES += QS_LOG_DISABLE