Qt5.14.2 揭秘Qt日志神器高效诊断程序潜在隐疾
对程序员而言,代码中的bug往往如同无影无踪的隐疾,影响着程序的健康运行。而及时有效的诊断手段则是治疗这些隐疾的良药。今天,我们将一窥Qt日志框架QLoggingCategory的神奇功效,探究它如何为你的Qt应用程序构筑坚实的诊断防火墙。
一、Qt日志框架简介
Qt内置了一个功能强大的日志框架,旨在帮助开发者高效诊断应用程序中潜在的问题。这套框架包含qDebug()、qInfo()、qWarning()和qCritical()等日志记录函数,以及QLoggingCategory等控制日志输出的工具类。
二、简单实践:qDebug输出
qDebug()无疑是最常用的日志输出函数,它会将日志信息输出到stderr标准错误流,从而统一输出到终端或者IDE集成工具的调试视图中。
qDebug() << "Hello Qt Log!";
qDebug() << "Value:" << 3.14;
QString str = "Debug Message";
qDebug() << str;
三、QLoggingCategory助力日志控制
借助QLoggingCategory,我们可以更细腻地控制不同日志信息的记录规则,甚至限制日志只输出在特定的平台或设备上。这对于分析复杂应用中的特定环节或组件情况极为有用。
// 1.定义日志类别
Q_LOGGINGCATEGORY(QT_EXAMPLE_MAIN, "qt.example.main")
Q_LOGGINGCATEGORY(QT_EXAMPLE_NETWORKING, "qt.example.networking", QtInfoMsg)// 2.根据类别名控制输出级别
QLoggingCategory::setFilterRules("qt.example.networking=true\nqt.example.main.debug=false");// 3.在代码中使用
qCDebug(QT_EXAMPLE_MAIN) << "Main log";
qCInfo(QT_EXAMPLE_NETWORKING) << "Network log";
QLoggingCategory允许我们在运行时动态设置日志级别,从而控制哪些级别的日志可以被输出。设置日志级别的方式很简单,使用QLoggingCategory::setFilterRules函数即可。
QLoggingCategory定义了以下几个日志级别:
- QtDebugMsg - Debug级别
- QtInfoMsg - 信息级别
- QtWarningMsg - 警告级别
- QtCriticalMsg - 严重级别
- QtFatalMsg - 致命级别
我们可以为每个日志类别设置单独的日志级别,或者为所有类别设置统一的全局级别。
下面是一些示例:
1、设置单个类别的日志级别:
Q_LOGGINGCATEGORY(APP_MAIN, "app.main")// 只输出APP_MAIN类别的WARNING及以上级别日志
QLoggingCategory::setFilterRules("app.main.warning=true");qCDebug(APP_MAIN) << "Ignored debug";
qCWarning(APP_MAIN) << "Warning message"; //会输出
2、设置所有类别的全局日志级别:
// 所有类别只输出CRITICAL及以上级别日志
QLoggingCategory::setFilterRules("*.critical=true");qCDebug(APP_MAIN) << "Ignored debug";
qCWarning(APP_MAIN) << "Ignored warning";
qCCritical(APP_MAIN) << "Critical error!"; //会输出
3、同时设置多个规则:
// APP_NETWORK类别只输出INFO及以上
// 其他类别只输出WARNING及以上
QLoggingCategory::setFilterRules("app.network.info=true\n*.warning=true");
可以看到,setFilterRules函数的参数是一个规则字符串,可以包含多条规则,以\n分隔。规则语法为:
<category>.debug|info|warning|critical|fatal=true|false
其中,category可以是具体的类别名或通配符*表示所有类别。等号后面指定是启用还是禁用该级别的日志输出。
我们也可以在程序启动时就设置好规则,比如通过命令行参数或配置文件传入。或者在运行过程中根据需求动态修改日志级别,实现灵活的日志控制。
此外,QtCreator还提供了一个非常方便的图形化界面来配置日志级别。在Analyzer->Logging->LoggingSettings中,我们可以可视化地启用禁用不同类别和级别的日志输出。
通过合理设置日志级别,我们可以在应用开发和调试的不同阶段,根据实际情况来控制输出精简的日志信息,提高诊断效率。
四、高级主题:详尽日志上下文
在实际开发中,我们往往需要获取更多辅助信息(如行号、函数名等),以确定问题发生的上下文环境。Qt提供了qDebug捕获器(QDebugStateSaverX)来记录详细的语句执行位置信息。
void myFunction(int c) {QDebugStateSaver stateSaver;qDebug() << "Entering myFunction(" << c << ")";// Function code...
}
五、QLoggingCategory其他常见用法
QLoggingCategory除了我们上面提到的控制日志输出规则和级别的功能之外,还有以下一些常见的用法:
1、将日志输出重定向到文件
通过QLoggingCategory::installMessageHandler函数,可以自定义日志输出的处理回调函数,将日志信息重定向写入到文件中,而不是直接输出到控制台。这在某些场景下非常有用,比如在服务器环境中捕获程序运行日志。
下面我们通过一个完整的示例代码来说明具体的实现步骤:
#include <QCoreApplication>
#include <QLoggingCategory>
#include <QFile>
#include <QTextStream>// 定义日志类别
Q_LOGGINGCATEGORY(LOG_CATEGORY, "example.log")// 自定义消息处理函数
void customMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{// 打开日志文件static QFile logFile("log.txt");if (!logFile.isOpen()) {logFile.open(QIODevice::WriteOnly | QIODevice::Append);}// 将日志写入文件QTextStream stream(&logFile);stream << qPrintable(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz "));switch (type) {case QtDebugMsg:stream << "Debug: ";break;case QtInfoMsg:stream << "Info: ";break;case QtWarningMsg:stream << "Warning: ";break;case QtCriticalMsg:stream << "Critical: ";break;case QtFatalMsg:stream << "Fatal: ";break;}stream << msg << " (" << context.file << ":" << context.line << ", " << context.function << ")" << endl;
}int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 安装自定义消息处理函数qInstallMessageHandler(customMessageHandler);// 使用日志类别输出日志qCDebug(LOG_CATEGORY) << "This is a debug message";qCInfo(LOG_CATEGORY) << "This is an info message";qCWarning(LOG_CATEGORY) << "This is a warning message";qCCritical(LOG_CATEGORY) << "This is a critical message";return a.exec();
}
这个示例中,我们首先定义了一个名为LOG_CATEGORY的日志类别。
然后实现了一个自定义的消息处理函数customMessageHandler。这个函数会在Qt输出日志时被调用,我们在函数内部打开了一个名为log.txt的文件,并将日志信息以特定的格式写入到文件中。
在main函数中,我们通过qInstallMessageHandler函数将自定义的customMessageHandler安装为Qt的全局消息处理程序。
接下来,我们就可以使用qCDebug、qCInfo等带类别的日志输出函数来输出日志了。由于我们已经安装了自定义的处理程序,所以这些日志信息会被重定向写入到log.txt文件中。
运行这个程序后,您可以查看log.txt文件的内容,里面会包含程序输出的各种级别的日志信息,格式类似于:
2023-05-18 14:36:52.131 Debug: This is a debug message (main.cpp:30, main)
2023-05-18 14:36:52.132 Info: This is an info message (main.cpp:31, main)
2023-05-18 14:36:52.132 Warning: This is a warning message (main.cpp:32, main)
2023-05-18 14:36:52.132 Critical: This is a critical message (main.cpp:33, main)
可以看到,每一条日志都包含了时间戳、日志级别、消息内容以及文件名、行号、函数名等上下文信息,方便我们分析和定位问题。
通过这种方式,我们就可以将Qt程序的日志信息持久化存储到文件中,不再依赖于控制台输出,从而方便了日志的收集和管理。您也可以根据实际需求,对这个自定义消息处理函数进行修改和扩展,比如增加日志文件的循环滚动等功能。
2、条件日志输出
通过 QtMsgType 参数,QLoggingCategory可以让你有条件地输出日志,比如只输出WARNING及以上级别的日志信息。这在生产环境中很有用,可以过滤掉一些不太重要的DEBUG级别的日志。
QLoggingCategory::setFilterRules("qt.example.main.info=false");
qCDebug(QT_EXAMPLE_MAIN) << "Too verbose"; //不会输出
qCWarning(QT_EXAMPLE_MAIN) << "Important warning"; //会输出
总之,在开发Qt应用的过程中,我们需要时刻保持对代码"内疾外馁"的警惕,及时发现并排查问题。QLoggingCategory这一强大的日志框架将是你的得力助手,指引你走出调试困境,让应用程序运转更加健康稳定。
相关文章:
Qt5.14.2 揭秘Qt日志神器高效诊断程序潜在隐疾
对程序员而言,代码中的bug往往如同无影无踪的隐疾,影响着程序的健康运行。而及时有效的诊断手段则是治疗这些隐疾的良药。今天,我们将一窥Qt日志框架QLoggingCategory的神奇功效,探究它如何为你的Qt应用程序构筑坚实的诊断防火墙。…...
Mac上设置环境变量PATH
一、配置文件有哪些 在Mac系统中,环境变量的配置文件主要包括以下几个: 文件名称描述/etc/paths系统级别的配置文件,系统启动时会加载它。/etc/profile系统级别的配置文件,所有用户登录时都会读取该文件。~/.bash_profile用户级别…...
Redis 全景图(1)--- 关于 Redis 的6大模块
这是我第一次尝试以长文的形式写一篇 Redis 的总结文章。这篇文章我想写很久了,只是一直碍于我对 Redis 的掌握没有那么的好,因此迟迟未动笔。这几天,我一直在看各种不同类型的 Redis 文章,通过阅读这些文章,引发了我对…...
Lambda表达式,Stream流
文章目录 Lambda表达式作用前提函数式接口特点 语法省略模式和匿名对象类的区别 Stream流思想作用三类方法获取方法单列集合(Collection[List,Set双列集合Map(不能直接获取)数组同一类型元素(Stream中的静态方法) 常见的中间方法终结方法收集方法 Optional类 Lambda表达式 作用…...
Apache Hive的基本使用语法(一)
一、数据库操作 创建数据库 create database if not exists myhive;查看数据库 use myhive; desc database myhive;创建数据库并指定hdfs存储 create database myhive2 location /myhive2;删除空数据库(如果有表会报错) drop database myhive;…...
Python爬虫详解:原理、常用库与实战案例
前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家:https://www.captainbed.cn/z ChatGPT体验地址 文章目录 前言引言:一、爬虫原理1. HTTP请求与响应过程2. 常用爬虫技术 二、P…...
搭建跨境电商电商独立站如何接入1688平台API接口|通过1688API接口采集商品通过链接搜索商品下单
接口设计|接口接入 对于mall项目中商品模块的接口设计,大家可以参考项目的Swagger接口文档,以Pms开头的接口就是商品模块对应的接口。 参数说明 通用参数说明 参数不要乱传,否则不管成功失败都会扣费url说明……d.cn/平台/API类型/ 平台&…...
【GlobalMapper精品教程】073:像素到点(Pixels-to-Points)从无人机图像轻松生成点云
文章目录 一、工具介绍二、生成点云三、生成正射四、生成3D模型五、注意事项一、工具介绍 Global Mapper v19引入的新的像素到点工具使用摄影测量原理,从重叠图像生成高密度点云、正射影像及三维模型。它使LiDAR模块成为已经功能很强大的的必备Global Mapper扩展功能。 打开…...
论文复现1:Mobilealoha
abstract:从人类演示中进行的模仿学习在机器人技术中表现出了令人印象深刻的表现。然而,大多数结果都集中在桌面操作上,缺乏一般有用任务所需的移动性和灵活性。在这项工作中,我们开发了一种用于模仿双手且需要全身控制的移动操纵任务的系统。我们首先推出 Mobile ALOHA,这…...
pycharm复习
目录 1.基础语法 2.判断语句 3.while循环 4.函数 5.数据容器 1.基础语法 1.字面量 2.注释: 单行注释# 多行注释" " " " " " 3.变量: 变量名 变量值 print:输出多个结果&#x…...
【SQLSERVER】批量导出所有作业或链接脚本
1.在Microsoft SQL Server Management Studio中选择–>视图(v)–>对象资源管理器详细信息(F7) 2.SSMS图形界面,左侧是“对象资源管理器”,右侧是“对象资源管理器详细信息”界面 3.左侧的“对象资源管理器”界面–>点击“SQLSserver代理”–…...
函数参数缺省和内联函数【C++】
文章目录 函数参数缺省函数参数缺省的条件和要求 内联函数内联函数的工作原理内联函数的定义方法内联函数的要求解决方法:直接在.h中定义内联函数的函数体 内联函数再Debug模式下默认是不展开的 函数参数缺省 顾名思义:可以少传一个/多个参数给函数&…...
javaWeb城市公交查询系统的设计与实现
一、选题背景 随着低碳生活的普及,人们更倾向于低碳环保的出行方式,完善公交系统无疑具有重要意义。公交是居民日常生活中最常使用的交通工具之一,伴随着我国经济繁荣和城市人口增长,出行工具的选择也变得越来越重要。政府在公共…...
企业案例:金蝶云星空对接旺店通·企业版
某知名化妆品企业,主要专注于化妆品,护肤品等研发,销售,生产于一体化的企业。企业的业务模式涉及比较广,有2B,2C和国内外电商领域。由于对内部业务流程的连贯性和数据的准确性比较关注。财务系统用的金蝶云星空&#x…...
wpsword求和操作教程
wpsword求和怎么操作: 1、首先,单纯的数据是无法求和的,所以我们必须要“插入”一个“表格” 2、接着将需要求和的数据填入到表格中。 3、填完后,进入“布局”选项卡。 4、然后打开其中的“公式” 5、在其中选择求和公式“SUM”并…...
Android 手机部署whisper 模型
Whisper 是什么? “Whisper” 是一个由OpenAI开发的开源深度学习模型,专门用于语音识别任务。这个模型能够将语音转换成文本,支持多种语言,并且在处理不同的口音、环境噪音以及跨语言的语音识别方面表现出色。Whisper模型的目标是提供一个高效、准确的工具,以支持自动字幕…...
通信术语:初学者入门指南(二)
1.SAR:Synthetic Aperture Radar合成孔径雷达,是一种雷达系统,通常用于地球或行星的遥感成像。相较于传统的实孔径雷达,SAR 通过在相对较长的时间内,对来自同一地点的多个雷达反射信号进行综合处理,实现了更…...
Java中使用MQTT客户端库实现TLS/SSL加密通信的示例
以下是一个完整的Java代码示例,展示了如何使用Eclipse Paho MQTT客户端库在Java中实现TLS/SSL加密的MQTT通信。在这个示例中,我们将创建一个简单的MQTT客户端,该客户端连接到支持TLS/SSL的MQTT代理,并发布和订阅消息。 首先&…...
【m122】webrtc的比较
uint16的比较IsNewerSequenceNumber 和 u32的比较LatestTimestamp G:\CDN\WEBRTC-DEV\libwebrtc_build\src\modules\include\module_common_types_public.h/** Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.** Use of this source code is governed …...
axios发送get请求但参数中有数组导致请求路径多出了“[]“的处理办法
一、情况 使用axios发送get请求携带了数组参数时,请求路径中就会多出[]字符,而在后端也会报错 二、解决办法 1、安装qs 当前项目的命令行中安装 npm install qs2、引入qs库(使用qs库来将参数对象转换为字符串) // 全局 import qs from qs Vue.proto…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...
