当前位置: 首页 > java >正文

Qt 中日志级别

在 Qt 中,日志级别主要通过 qDebug()qInfo()qWarning()qCritical() 和 qFatal() 这几个宏来区分。它们分别对应不同的严重程度。

一、Qt 内置的日志级别(按严重程度从低到高排序)

宏 / 函数日志级别说明默认行为
qDebug()Debug调试信息。用于程序开发调试阶段输出详细信息,发布版本通常关闭。输出到 stderr(或系统日志)。
qInfo()Info信息消息。用于输出程序正常运行时的状态信息(如启动、配置加载成功)。输出到 stderr(或系统日志)。
qWarning()Warning警告消息。表明发生了意外情况,但应用程序仍能继续运行(如解析配置文件失败使用默认值)。输出到 stderr(或系统日志)。
qCritical()Critical严重错误消息。表明发生了严重错误,应用程序可能无法继续正常运行(如磁盘空间不足、关键功能失效)。输出到 stderr(或系统日志)。
qFatal()Fatal致命错误消息。在输出此消息后,应用程序会自动中止(abort)。用于发生了不可恢复的错误(如断言失败、关键数据损坏)。输出到 stderr 并调用 abort() 终止程序。

二、 基本使用示例

cpp

#include <QCoreApplication>
#include <QDebug>
#include <QInfo>
#include <QWarning>
#include <QCritical>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);qDebug()   << "This is a DEBUG message. Value of argc:" << argc;qInfo()    << "This is an INFO message. Application started successfully.";qWarning() << "This is a WARNING message. Configuration file not found, using defaults.";qCritical() << "This is a CRITICAL message. Failed to connect to the database!";// 下面的语句会终止程序// if (someCriticalError)//     qFatal("Fatal error: Unable to start the core component. Aborting.");return a.exec();
}

输出示例:

text

debug: This is a DEBUG message. Value of argc: 1
info: This is an INFO message. Application started successfully.
warning: This is a WARNING message. Configuration file not found, using defaults.
critical: This is a CRITICAL message. Failed to connect to the database!

三、 高级控制:分类日志(Categorized Logging)和规则(Rules)

从 Qt 5.2 开始,引入了更精细的日志控制系统。你可以为不同的日志类别(Category)设置不同的级别和输出规则。

a. 定义日志类别

使用 Q_LOGGING_CATEGORY 宏来定义一个类别。

cpp

// 在头文件中定义
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(myAppCore)
Q_DECLARE_LOGGING_CATEGORY(myAppUi)// 在源文件中实现
Q_LOGGING_CATEGORY(myAppCore, "myapp.core")
Q_LOGGING_CATEGORY(myAppUi, "myapp.ui")
b. 使用类别日志

使用 qCDebug()qCInfo()qCWarning()qCCritical() 宏。

cpp

qCDebug(myAppCore) << "Core module initialized.";
qCWarning(myAppUi) << "UI component took too long to respond.";
示例

假设你的应用叫 "ChatApp":

cpp

// main.cpp
#include <QApplication>
#include <QLoggingCategory>// 定义日志类别
Q_LOGGING_CATEGORY(chatapp, "chatapp")
Q_LOGGING_CATEGORY(chatappNetwork, "chatapp.network")
Q_LOGGING_CATEGORY(chatappMessage, "chatapp.message")int main(int argc, char *argv[])
{QApplication app(argc, argv);app.setApplicationName("ChatApp");qCInfo(chatapp) << "ChatApp started";qCDebug(chatappNetwork) << "Network module initialized";return app.exec();
}

输出结果

在 Qt 的 Debug 构建模式下,通常能看到:

text

chatapp.info: ChatApp started
chatapp.network.debug: Network module initialized

在 Release 构建模式下,默认可能只看到:

text

chatapp.info: ChatApp started
c. 通过环境变量配置日志规则

你可以在程序启动前设置 QT_LOGGING_RULES 环境变量来控制哪些类别的日志应该被输出。

示例:

  • 禁用所有调试日志:

    bash

    export QT_LOGGING_RULES="*.debug=false"
    ./myapp
  • 启用 myapp.core 类别的调试日志,禁用其他所有调试日志:

    bash

    export QT_LOGGING_RULES="myapp.core.debug=true;*.debug=false"
    ./myapp
  • 在 Windows 命令提示符中:

    cmd

    set QT_LOGGING_RULES=myapp.core.debug=true;*.debug=false
    myapp.exe
d. 在代码中配置规则

你也可以在代码中通过 QLoggingCategory::setFilterRules() 来设置规则。

cpp

int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 在代码中设置规则QString rules;rules = "*.debug=false\n""*.info=true\n""*.warning=true\n""*.critical=true\n""myapp.*.debug=true\n""qt.*.debug=false";QLoggingCategory::setFilterRules(rules);// ... 其余代码 ...return a.exec();
}

四、配置文件来控制日志输出

日志级别输出控制权交给logging.conf文件,通过修改文件增加或减少日志打印输出。

1. log规则读取类

logger.h

#ifndef LOGGER_H
#define LOGGER_H#include <QString>
#include <QMap>class Logger
{
public:static bool loadConfig(const QString &configPath);static void setDefaultConfig();static void enableDebug(bool enable);static void enableCategory(const QString &category, bool enable);static QString getCurrentRules();private:Logger() = delete;// 静态变量用于存储当前规则static QMap<QString, bool> m_rules;static void applyRules();static void parseAndAddRule(const QString &ruleLine);
};#endif // LOGGER_H

logger.cpp

#include "logger.h"
#include <QLoggingCategory>
#include <QFile>
#include <QTextStream>
#include <QSettings>
#include <QDebug>
#include <QRegularExpression>// 初始化静态成员变量
QMap<QString, bool> Logger::m_rules;bool Logger::loadConfig(const QString &configPath)
{QFile file(configPath);if (!file.exists()) {qWarning() << "Logging config file not found:" << configPath;return false;}if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {qWarning() << "Cannot open logging config:" << configPath;return false;}// 清空现有规则m_rules.clear();QTextStream in(&file);QString rules;while (!in.atEnd()) {QString line = in.readLine().trimmed();// 跳过注释和空行if (line.startsWith('#') || line.startsWith("//") || line.isEmpty()) {continue;}parseAndAddRule(line);}file.close();applyRules();qInfo() << "Logging configuration loaded successfully";return true;
}void Logger::parseAndAddRule(const QString &ruleLine)
{QString pattern;bool enabled = true;if (ruleLine.contains('=')) {// 处理 key=value 格式int equalsIndex = ruleLine.indexOf('=');pattern = ruleLine.left(equalsIndex).trimmed();QString value = ruleLine.mid(equalsIndex + 1).trimmed();if (value.compare("false", Qt::CaseInsensitive) == 0 || value == "0") {enabled = false;} else {enabled = true;}} else {// 处理简单格式pattern = ruleLine;enabled = true;}if (!pattern.isEmpty()) {m_rules[pattern] = enabled;}
}void Logger::applyRules()
{QString rulesStr;QMap<QString, bool>::const_iterator it;for (it = m_rules.constBegin(); it != m_rules.constEnd(); ++it) {rulesStr += QString("%1=%2\n").arg(it.key()).arg(it.value() ? "true" : "false");}QLoggingCategory::setFilterRules(rulesStr);
}void Logger::setDefaultConfig()
{m_rules.clear();// 设置默认规则m_rules["*.debug"] = false;m_rules["*.info"] = true;m_rules["*.warning"] = true;m_rules["*.critical"] = true;m_rules["myapp.*.debug"] = true;m_rules["myapp.network.info"] = true;m_rules["myapp.database.warning"] = true;m_rules["qt.*.debug"] = false;m_rules["qt.*.info"] = false;applyRules();qInfo() << "Using default logging configuration";
}void Logger::enableDebug(bool enable)
{// 更新所有debug相关的规则QMap<QString, bool> newRules = m_rules;QMap<QString, bool>::iterator it;for (it = newRules.begin(); it != newRules.end(); ++it) {if (it.key().endsWith(".debug")) {it.value() = enable;}}// 也更新全局debug设置newRules["*.debug"] = enable;m_rules = newRules;applyRules();qInfo() << "Debug mode" << (enable ? "enabled" : "disabled");
}void Logger::enableCategory(const QString &category, bool enable)
{// 更新特定类别的所有规则QMap<QString, bool> newRules = m_rules;QMap<QString, bool>::iterator it;for (it = newRules.begin(); it != newRules.end(); ++it) {if (it.key().startsWith(category + ".")) {it.value() = enable;}}m_rules = newRules;applyRules();qInfo() << "Category" << category << (enable ? "enabled" : "disabled");
}QString Logger::getCurrentRules()
{QString rules;QMap<QString, bool>::const_iterator it;for (it = m_rules.constBegin(); it != m_rules.constEnd(); ++it) {rules += QString("%1=%2\n").arg(it.key()).arg(it.value() ? "true" : "false");}return rules;
}

2. 配置文件示例

logging.conf

# 日志配置文件
# 注释以 # 或 // 开头# 全局设置
*.debug=false
*.info=true
*.warning=true
*.critical=true# 应用程序特定设置
myapp.main.debug=true
myapp.network.info=true
myapp.database.warning=true# Qt 内部模块
qt.*.debug=false
qt.core.info=false

3. 在应用程序中集成

// 在应用程序初始化时
void initLogger()
{// 尝试从文件加载配置QString configPath = QCoreApplication::applicationDirPath() + "/logging.conf";if (!Logger::loadConfig(configPath)) {// 使用默认配置Logger::setDefaultConfig();}// 获取当前规则QString currentRules = Logger::getCurrentRules();qDebug() << "Current logging rules:" << currentRules;
}

修改logging.conf配置文件debug=flase,debug=true等值,可以控制日志级别输出。
比如:*.debug=true,在程序应用中qDebug()语句的内容就打印输出。*.debug=false,在程序应用中qDebug()语句的内容不会打印输出。*.info=true,在程序应用中qInfo()语句的内容就打印输出。

http://www.xdnf.cn/news/19005.html

相关文章:

  • ArcGIS+Fragstats:土地利用统计分析、景观格局指数计算与地图制图
  • Android Keystore签名文件详解与安全防护
  • AI视频生成工具全景对比:元宝AI、即梦AI、清影AI和Vidu AI
  • 【贪心 单调栈】P10334 [UESTCPC 2024] 饮料|普及+
  • 工业 5G + AI:智能制造的未来引擎
  • Day16_【机器学习建模流程】
  • 【Rust】 3. 语句与表达式笔记
  • Java HTTP 请求:Unirest 使用指南及与 HttpClient 对比
  • .Net Core Web 架构(Request Pipeline)的底层实现
  • 自己定义的模型如何用hf的from_pretrained
  • Linux(一) | 初识Linux与目录管理基础命令掌握
  • 测试题ansible临时命令模块
  • CuTe C++ 简介01,从示例开始
  • imx6ull-驱动开发篇47——Linux SPI 驱动实验
  • Electron解压缩文件
  • hive on tez为什么写表时,要写临时文件到hdfs目录
  • docker 1分钟 快速搭建 redis 哨兵集群
  • 配置nginx.conf (增加21001端口实例操作)
  • 医疗AI时代的生物医学Go编程:高性能计算与精准医疗的案例分析(三)
  • [灵动微电子 MM32BIN560CN MM32SPIN0280]读懂电机MCU之比较器
  • jQuery 从入门到实践:基础语法、事件与元素操作全解析
  • mac电脑双屏显示时程序坞跑到副屏的解决方法
  • 机器视觉学习-day10-图像添加水印
  • Mybatis 与 Springboot 集成过程详解
  • Kubernetes一EFK日志架构
  • Ovis2.5技术解密:原生分辨率与“反思模式”如何铸就新一代MLLM王者
  • 嵌入式学习日志————实验:串口发送串口发送+接收
  • 2025年渗透测试面试题总结-37(题目+回答)
  • 2024年06月 Python(三级)真题解析#中国电子学会#全国青少年软件编程等级考试
  • 零基础-力扣100题从易到难详解(持续更新1-10题)