Qt日志输出及QsLog日志库

news2024/11/14 15:02:43

目录

  • 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_OUTPUT
    QT_NO_DEBUG_OUTPUT
    QT_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.coloradmin.cn/o/2152070.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Why is OpenAI image generation Api returning 400 bad request in Unity?

题意&#xff1a;为什么 OpenAI 图像生成 API 在 Unity 中返回 400 Bad Request 错误&#xff1f; 问题背景&#xff1a; Im testing out dynamically generating images using OpenAI API in Unity. Amusingly, I actually generated most of this code from chatGPT. 我正在…

idea中.git文件夹存在但是没有git功能列表

1.问题&#xff1a; 该项目中已经将.git文件夹置入了&#xff0c;但是idea中却没有git相关的功能列表&#xff0c;如图&#xff1a; 2.解决办法&#xff1a; 在【文件】-【设置】-【版本控制】-【目录映射】中添加目录映射应用就好了 &#xff08;【File】 -> 【S…

网络资源模板--Android Studio 图书借阅App

目录 一、项目演示 二、项目测试环境 三、项目详情 四、完整的项目源码 一、项目演示 网络资源模板--图书借阅App 二、项目测试环境 三、项目详情 首页 这段代码是一个 Android 应用的 MainActivity 类&#xff0c;功能简要总结如下&#xff1a; 1. **界面设置**&#xf…

Hutool:Java开发者的瑞士军刀

有想念&#xff0c;才是团圆&#xff1b;在一起&#xff0c;便是中秋。 在Java的世界里&#xff0c;有这样一个工具库&#xff0c;它小巧而强大&#xff0c;功能丰富且易于使用&#xff0c;它就是Hutool。Hutool是一个Java工具包&#xff0c;旨在减少Java开发人员在开发过程中…

Oracle数据库逻辑与物理结构操作

一、实验步骤 1、查询所有DBA和USER开头的静态数据字典 2、查询所有V$动态性能视图 3、查询当前数据库中的表空间信息 ①查询和TABLESPACE相关的数据字典 ②通过动态性能视图查询表空间信息 ③通过数据字典查询表空间信息 4、操作数据文件 &#xff08;1&#xff09;向 ORC…

JavaWeb JavaScript 11.XML —— 配置文件

生活想埋没我&#xff0c;没想到我是颗种子 —— 24.9.19 一、XML 1.什么是XML XML是EXtensible Markup Languge的缩写&#xff0c;翻译过来就是可扩展标记语言。所以很明显&#xff0c;XML和HTML一样都是标记语言&#xff0c;也就是说它们的基本语法都是标签 可扩展 三个字…

网络:UDP协议

个人主页 &#xff1a; 个人主页 个人专栏 &#xff1a; 《数据结构》 《C语言》《C》《Linux》 文章目录 前言UDP协议报头和有效载荷分离的问题有效载荷向上交付的问题&#xff0c;也就是交给哪个进程&#xff1f;怎么确定把报文收全了&#xff1f;UDP报头是如何封装的呢&…

JavaWeb纯小白笔记02:Tomcat的使用:发布项目的三种方式、配置虚拟主机、配置用户名和密码

通过Tomcat进行发布项目的目的是为了提供项目的访问能力&#xff1a;Tomcat作为Web服务器&#xff0c;能够处理HTTP请求和响应&#xff0c;将项目的内容提供给用户进行访问和使用。 一.Tomcat发布项目的三种方式&#xff1a; 第一种&#xff1a;直接在Tomcat文件夹里的webapp…

数学建模 第一讲 - 概论

一、什么是数学模型 一个栗子 例 1.1 一只装满水的圆柱型桶&#xff0c;底半径为 1米&#xff0c;高为 2米&#xff0c;底部有一直径为 0.1 米的洞。问桶流空要多少时间? 数学模型是对于一个特定的对象为了一个特定目标&#xff0c;根据事物的内在规律&#xff0c;作出一些必…

防止用户过于轻松采集网页内容的方法

面对AI&#xff0c;所有禁止采集网页内容的功能都是徒劳&#xff0c;最不济截图后采集文字总简单了吧&#xff1f;能做的就是增加一点点人工采集的难度。 以下总结一下 一、注册用户 必须注册才能浏览全部内容&#xff0c;那么这样就可以针对用户控制其浏览次数&#xff0c;浏…

ActiveMQ、RabbitMQ 和 Kafka 在 Spring Boot 中的实战

在现代的微服务架构和分布式系统中&#xff0c;消息队列 是一种常见的异步通信工具。消息队列允许应用程序之间通过 生产者-消费者模型 进行松耦合、异步交互。在 Spring Boot 中&#xff0c;我们可以通过简单的配置来集成不同的消息队列系统&#xff0c;包括 ActiveMQ、Rabbit…

多层感知机paddle

多层感知机——paddle部分 本文部分为paddle框架以及部分理论分析&#xff0c;torch框架对应代码可见多层感知机 import paddle print("paddle version:",paddle.__version__)paddle version: 2.6.1多层感知机&#xff08;MLP&#xff0c;也称为神经网络&#xff0…

QEMU:模拟 ARM 大端字节序运行环境

文章目录 1. 前言2. ARM 大小端模拟测试2.1 裸机模拟测试2.1.1 大端模拟测试2.1.2 小端模拟测试 2.2 用户空间模拟测试2.2.1 大端模拟测试2.2.2 小端模拟测试 2.3 结论 3. 参考链接 1. 前言 限于作者能力水平&#xff0c;本文可能存在谬误&#xff0c;因此而给读者带来的损失&…

leetcode刷题3

文章目录 前言回文数1️⃣ 转成字符串2️⃣ 求出倒序数再比对 正则表达式匹配[hard]1️⃣ 动态规划 盛最多水的容器1️⃣ 遍历分类2️⃣ 双指针贪心 最长公共前缀1️⃣ 遍历&#xff08;zip解包&#xff09; 三数之和1️⃣ 双指针递归 最接近的三数之和1️⃣ 迭代一次双指针 电…

携手阿里云CEN:共创SD-WAN融合广域网

在9月19日举行的阿里云云栖大会上&#xff0c;犀思云作为SD-WAN领域的杰出代表及阿里云的SD-WAN重要合作伙伴&#xff0c;携手阿里云共同推出了创新的企业上云方案——Fusion WAN智连阿里云解决方案。这一创新方案不仅彰显了犀思云在SD-WAN技术领域的深厚积累&#xff0c;更体现…

前端web端项目运行的时候没有ip访问地址

我们发现 没有netWork 的地址 导致 团队内其他同学无法打开我们的地址 进行访问 在page.json 中的运行 指令中 添加 --host 记得加上空格 这样我们就可以看到这个地址了 团队其他同学 就可以访问我们这个地址了

Resnet50网络——口腔癌病变识别

一 数据准备 1.导入数据 import matplotlib.pyplot as plt import tensorflow as tf import warnings as w w.filterwarnings(ignore) # 支持中文 plt.rcParams[font.sans-serif] [SimHei] # 用来正常显示中文标签 plt.rcParams[axes.unicode_minus] False # 用来正常显示负…

2024华为杯研究生数学建模竞赛(研赛)选题建议+初步分析

难度&#xff1a;DE<C<F&#xff0c;开放度&#xff1a;CDE>F。 华为专项的题目&#xff08;A、B题&#xff09;暂不进行选题分析&#xff0c;不太建议大多数同学选择&#xff0c;对自己专业技能有很大自信的可以选择华为专项的题目。后续会直接更新A、B题思路&#…

计算机网络传输层---课后综合题

线路&#xff1a;TCP报文下放到物理层传输。 TCP报文段中&#xff0c;“序号”长度为32bit&#xff0c;为了让序列号不会循环&#xff0c;则最多能传输2^32B的数据&#xff0c;则最多能传输&#xff1a;2^32/1500B个报文 结果&#xff1a; 吞吐率一个周期内传输的数据/周期时间…

2024/9/19、20 数学20题

极大线性无关组&#xff1a;