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()语句的内容就打印输出。