Qt日志输出及QsLog日志库

目录

  • 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提供了禁用qInfoqWarningqDebug输出的宏,qCriticalqFatal是错误不能屏蔽!

CMakeLists.txt 文件中禁用日志输出

在CMakeLists.txt文件中添加如下三行,即可禁用qInfoqWarningqDebug的输出。

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 文件中添加如下三行,即可禁用 qInfoqWarningqDebug 的输出。

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文件同级。

QsLog目录

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/428541.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

有奖直播 | onsemi IPM 助力汽车电气革命及电子化时代冷热管理

在全球汽车行业向电气化和智能化转型的浪潮中&#xff0c;功率管理技术的创新和应用成为了关键驱动力。作为全球领先的半导体解决方案供应商&#xff0c;onsemi&#xff08;安森美&#xff09;致力于通过其先进的智能功率模块&#xff08;IPM&#xff09;技术&#xff0c;推动汽…

[Linux#55][网络协议] 序列化与反序列化 | TcpCalculate为例

目录 1. 理解协议 1.1 结构化数据的传输 序列化与反序列化 代码感知&#xff1a; Request 类 1. 构造函数 2. 序列化函数&#xff1a;Serialize() 3. 反序列化函数&#xff1a;DeSerialize() 补充 4. 成员变量 Response 类 1. 构造函数 2. 序列化函数&#xff1a;…

JavaWeb - 5 - 前端工程化

一.前后端分离开发 前后端混合开发 缺点&#xff1a;沟通成本高&#xff0c;分工不明确&#xff0c;不便管理&#xff0c;不便维护拓展 前后端分离开发 当前最为主流的开发模式&#xff1a;前后端分离 前后端分离开发中很重要的是API接口文档&#xff08;如&#xff1a;YApi&…

胤娲科技:谷歌DeepMind祭出蛋白质设计新AI——癌症治疗迎来曙光

在科技的浩瀚星空中&#xff0c;DeepMind的“阿尔法”家族总是能带来令人瞩目的璀璨光芒。这一次&#xff0c;它们再次以惊人的姿态&#xff0c; 将AI的触角深入到了生命的微观世界——蛋白质设计领域&#xff0c;为我们描绘了一幅未来医疗的宏伟蓝图。 想象一下&#xff0c;一…

Scrapy爬虫实战——某瓣250

# 按照我个人的习惯&#xff0c;在一些需要较多的包作为基础支撑的项目里&#xff0c;习惯使用虚拟环境&#xff0c;因为这样能极大程度的减少出现依赖冲突的问题。依赖冲突就比如A、B、C三个库&#xff0c;A和B同时依赖于C&#xff0c;但是A需要的C库版本大于N&#xff0c;而B…

VUE3配置路由(超级详细)

第一步创建vue3的项目

多版本node管理工具nvm

什么是nvm&#xff1f; 在项目开发过程中&#xff0c;使用到vue框架技术&#xff0c;需要安装node下载项目依赖&#xff0c;但经常会遇到node版本不匹配而导致无法正常下载&#xff0c;重新安装node却又很麻烦。为解决以上问题&#xff0c;nvm&#xff1a;一款node的版本管理工…

微服务-- Sentinel的使用

目录 Sentinel&#xff1a;微服务的哨兵 生态系统景观 sentinel与spring cloud Hystrix 对比 Sentinel 主要分为两部分 Sentinel安装与使用 Sentinel的控制规则 流控规则 流控规则的属性说明 新增流控规则 关联流控模式 SentinelResource注解的使用 SentinelResou…

mysql-死锁

文章目录 1、概念1.1、创建表 account1.2、id 自动创建 主键索引 primary1.3、name 没有创建索引 2、产生死锁的必要条件2.1、此时 name 没有创建 索引 3、如何处理死锁3.1、方式1&#xff1a;等待&#xff0c;直到超时&#xff08;innodb_lock_wait_timeout50s&#xff09;3.2…

GRE隧道在实际部署中的优化、局限性与弊端

GRE的其他特性 上一篇光讲解配置就花了大量的篇幅&#xff0c;还一些特性没有讲解的&#xff0c;这里在来提及下。 1、动态路由协议 在上一篇中是使用的静态路由&#xff0c;那么在动态路由协议中应该怎么配置呢&#xff1f; undoip route-static 192.168.20.0 255.255.255.0 …

element-plus的菜单组件el-menu

菜单是几乎是每个管理系统的软件系统中不可或缺的&#xff0c;element-plus提供的菜单组件可以快速完成大部分的菜单的需求开发&#xff0c; 该组件内置和vue-router的集成&#xff0c;使用起来很方便。 主要组件如下 el-menu 顶级菜单组件 主要属性 mode:决定菜单的展示模式…

2024/9/20 使用QT实现扫雷游戏

有三种难度初级6x6 中级10x10 高级16x16 完成游戏 游戏失败后&#xff0c;无法再次完成游戏&#xff0c;只能重新开始一局 对Qpushbutton进行重写 mybutton.h #ifndef MYBUTTON_H #define MYBUTTON_H #include <QObject> #include <QWidget> #include <QPus…

2024年8月HarmonyOS鸿蒙应用开发者高级认证全新题库

有题库在手&#xff0c;一小时轻松拿下鸿蒙高级。你们需要也可以无偿分享哦&#xff01; 项目需要为不同的设备形态(如手机 、 智能手表)提供定制化构建 。请说明如何在 DevEcostudio 中 设置不同的构建配置&#xff0c; 以生成针对不同设备的 hap 包&#xff1a; 在模块级别 b…

JavaWeb的Filter详解

过滤器Filter 什么是Filter&#xff1f; 依据字面上的中文意思为过滤器。Filter的作用 当用户的请求到达指定的URL之前&#xff0c;可以借助Filter来改变这些请求的内容&#xff1b;同样地&#xff0c;当响应结果到达客户端之前&#xff0c;可以使用Filter修改输出的内容。什么…

【数据结构入门】排序算法之三路划分与非比较排序

文章目录 前言 一、三路划分优化 1.1. 基本思想 1.2. 实现步骤 1.3. 优点 1.4 代码实现 二、非比较排序 2.1 计数排序 2.1.1基本思想 2.1.2具体步骤 2.1.3算法特性 2.1.4算法实现 2.2 基数排序 2.2.1基本思想 2.2.2具体步骤 2.2.3 基数排序的方法 2.2.4算法特…

MongoDB在Linux系统中的安装与配置指南

在这篇文章中&#xff0c;我们将介绍如何在CentOS 7服务器上安装MongoDB&#xff0c;并通过DataX将数据从MongoDB迁移到MySQL数据库。这将包括MongoDB的安装、配置、数据准备以及使用DataX进行数据迁移的详细步骤。 MongoDB简介 MongoDB是一个高性能、开源、无模式的文档型数据…

Leetcode面试经典150题-97.交错字符串

给定三个字符串 s1、s2、s3&#xff0c;请你帮忙验证 s3 是否是由 s1 和 s2 交错 组成的。 两个字符串 s 和 t 交错 的定义与过程如下&#xff0c;其中每个字符串都会被分割成若干 非空 子字符串 &#xff1a; s s1 s2 ... snt t1 t2 ... tm|n - m| < 1交错 是…

Springboot3 + MyBatis-Plus + MySql + Uniapp 实现商品规格选择sku(附带自设计数据库,最新保姆级教程)

Springboot3 MyBatis-Plus MySql Uniapp 实现商品规格选择sku&#xff08;附带自设计数据库&#xff0c;最新保姆级教程&#xff09; 1、效果展示2、数据库设计2.1 商品表2.2 商品价格和规格中间表2.3 商品规格表 3、后端代码3.1 model3.2 vo3.3 mapper、server、serverImp3…

使用express或koa或nginx部署history路由模式的单页面应用

使用hash模式会有#&#xff0c;影响美观&#xff0c;所以使用history模式会是个更好的选择。 前端项目打包上线部署&#xff0c;可以使用下面的方式部署history模式的项目&#xff0c;下面以 jyH5 为例 expressjs部署 express脚手架搭建的app.js中添加如下代码&#xff1a; …

CDA Level 1 业务数据分析

目录 理解业务数据分析方法、掌握业务数据分析流程、能够使用及设计创建业务指标、能够结合业务模型及业务分析方法正确理解业务问题&#xff0c;找到问题原因&#xff0c;并能够提出解决问题建议&#xff0c;这个章节的应用会考的比较多&#xff08;终于正经起来了呢&#xf…