Qt雜談7.淺談Qt日誌框架那些事

1 概述

Qt日誌框架是Qt提供的用於日誌記錄和輸出的模塊。它提供了靈活而強大的日誌系統,可以幫助開發者在應用程序中有效地管理和記錄日誌。

它的主要特性包括:

  • 日誌類別和級別: 可以定義不同的日誌類別和級別,例如調試、信息、警告、錯誤等。這樣可以更好地組織和分類日誌消息。
  • 過濾和記錄控制: 可以基於日誌級別和類別設置過濾規則,選擇記錄哪些日誌消息並輸出到哪些目標,如控制檯、文件、網絡等。
  • 動態調整: 在運行時可以動態調整日誌的過濾規則和記錄目標,以滿足不同階段和需求的日誌記錄需求。
  • 多線程支持: 可以在多線程環境中安全使用日誌系統,確保日誌消息的正確記錄和輸出。

Qt 的日誌框架是建立在 QLoggingCategory 類的基礎上的。QLoggingCategory 類是用來管理和控制 Qt 日誌輸出的核心類,它提供了控制日誌消息輸出級別、設置過濾規則、安裝自定義過濾器等功能,以便開發人員能夠更靈活地控制應用程序的日誌輸出,從而方便調試、問題排查和日誌輸出的定製化。

2 實際應用

2.1 基本流程

假設有一個使用Qt編寫的圖形用戶界面應用程序,其中包含網絡模塊和數據庫模塊。我們可以在每個模塊的頭文件中使用Q_DECLARE_LOGGING_CATEGORY宏來聲明相應的日誌類別:

// networkmodule.h
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(networkModule)

// databasemodule.h
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(databaseModule)

然後,在對應的源文件中使用Q_LOGGING_CATEGORY宏定義日誌類別的實例:

// networkmodule.cpp
#include "networkmodule.h"
Q_LOGGING_CATEGORY(networkModule, "networkmodule")

// databasemodule.cpp
#include "databasemodule.h"
Q_LOGGING_CATEGORY(databaseModule, "databasemodule")

現在假設我們想要將網絡模塊的日誌消息輸出到控制檯,並只保留警告級別以上的消息,而數據庫模塊的日誌消息則同時輸出到控制檯和日誌文件中。

可以按照如下方式進行配置:

QLoggingCategory::setFilterRules("networkmodule.debug=false\n"
                                "networkmodule.warning=true\n"
                                "databasemodule.debug=true\n"
                                "databasemodule.warning=true");

在這個例子中,設置了日誌類別的過濾規則。對於網絡模塊,禁用了調試級別的日誌消息輸出,只允許警告級別的消息輸出;而對於數據庫模塊,允許所有級別的消息輸出。

隨後,使用qCDebug或qCWarning等宏輸出的日誌消息將根據這些過濾規則進行處理,符合規則的消息將被輸出到指定的日誌目標中。這種靈活的配置方式可以根據實際需求,定製化地管理不同模塊的日誌輸出行爲。

2.2 涉及的宏

Q_DECLARE_LOGGING_CATEGORY 和 Q_LOGGING_CATEGORY 是 Qt 框架中用於日誌記錄的兩個宏,它們分別用於不同的場景。

  • Q_DECLARE_LOGGING_CATEGORY:用於類的聲明中聲明日誌類別,通常情況下,會將這個宏放在類的定義中,以便在類的實現文件中使用聲明的日誌類別進行日誌輸出。這樣可以讓每個類都有自己的日誌類別,並進行更細粒度的日誌控制。

  • Q_LOGGING_CATEGORY:用於在全局範圍內定義全局的日誌類別,通常情況下,會將這個宏放在全局範圍的一個源文件中,以定義全局的日誌類別供整個項目使用。

Q_LOGGING_CATEGORY接受兩個參數來定義一個自定義的日誌類別:Q_LOGGING_CATEGORY(category, categoryName),category指定日誌類別的名稱,通常是一個全局變量,它必須是一個有效的標識符;categoryName指定日誌類別的顯示名稱,是一個字符串,用於在日誌輸出中標識該類別。

這兩個宏一起使用,可以更好地管理和組織項目中的日誌輸出,提高日誌的可維護性和靈活性。

2.3 完整示例

  1. 首先,在頭文件中使用 Q_DECLARE_LOGGING_CATEGORY 宏聲明一個日誌類別。通常,將它放在類的聲明中,以便每個類都有自己的日誌類別。
// myclass.h
#include <QObject>
#include <QLoggingCategory>

Q_DECLARE_LOGGING_CATEGORY(myClassLog)

class MyClass : public QObject
{
    Q_OBJECT

public:
    MyClass(QObject *parent = nullptr);

public slots:
    void doSomething();
};
  1. 在實現文件中使用 Q_LOGGING_CATEGORY 宏來定義並初始化日誌類別。通常,將它放在全局範圍的一個源文件中。
// myclass.cpp
#include "myclass.h"

Q_LOGGING_CATEGORY(myClassLog, "myclass")

MyClass::MyClass(QObject *parent)
    : QObject(parent)
{
    //qCDebug(<日誌類別>) << "日誌消息"
    qCDebug(myClassLog) << "MyClass constructor called";
}

void MyClass::doSomething()
{
    qCInfo(myClassLog) << "Doing something";
    // ...
}

qCDebug是Qt框架提供的宏,用於輸出調試級別的日誌消息,與qDebug相比,qCDebug允許通過Qt的日誌類別和過濾規則來控制是否輸出日誌消息,並可以進一步定製化日誌的行爲;qDebug通常用於快速調試和測試,默認的日誌類別名稱是 “default”,這意味着,如果沒有爲日誌消息指定特定的日誌類別,那麼消息將被髮送到名爲 “default” 的日誌類別中。而qCDebug更適合在較大的項目中使用,並且對於調試輸出有更多的配置需求,需要顯式地指定日誌類別。

  1. 在代碼的其他位置,使用類中聲明的日誌類別進行日誌輸出。
#include <QCoreApplication>
#include "myclass.h"

Q_LOGGING_CATEGORY(globalLog, "global")

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qCInfo(globalLog) << "Application started";

    MyClass myObject;
    myObject.doSomething();

    qCWarning(myClassLog) << "Warning message";

    qCInfo(globalLog) << "Application finished";

    return a.exec();
}

注意:對於全局日誌類別 globalLog,通常來說是不需要顯式聲明的。在許多情況下,Qt 應用程序中的全局日誌類別不需要單獨聲明,而是直接在全局範圍內使用 Q_LOGGING_CATEGORY 宏進行定義。

  1. 結果輸出
global: Application started
myclass: MyClass constructor called
myclass: Doing something
myclass: Warning message
global: Application finished

2.4 日誌過濾

前面也有提及到,QLoggingCategory 類可以使用 setFilterRules() 方法來配置日誌過濾規則,該方法允許定義哪些日誌類別和級別應該被記錄。配置規則的格式如下:

QLoggingCategory::setFilterRules("categoryName.rule=type");

其中,每個規則由以下部分組成:

  • categoryName:日誌類別的名稱,可以是預定義的類別,也可以是自定義類別。
  • rule:日誌級別或特定的過濾規則。
  • type:要應用於該類別的規則類型,可以是 true(記錄該級別),false(不記錄該級別),或者整數值(記錄特定級別及比它更高的級別)。

例如:

QLoggingCategory::setFilterRules("myapp.debug=false\nmyapp.warning=true");

在這個示例中,規則表示對於名爲 myapp 的日誌類別,不記錄調試級別的日誌消息,只記錄警告級別的日誌消息。

針對2.3節的例子,大家可以自行配置過濾規則,看看是否和預期效果一致。

3 總結

Qt日誌框架提供了強大的日誌功能,可以方便地在應用程序中輸出日誌消息並進行管理。使用 Q_DECLARE_LOGGING_CATEGORY 宏可以在類中聲明日誌類別,使用 Q_LOGGING_CATEGORY 宏可以在全局範圍內定義和初始化日誌類別。通過這些日誌類別,我們可以利用 qCDebug()、qCInfo()、qCWarning() 等函數輸出不同級別的日誌信息。此外,可以根據需要設置特定的過濾條件,過濾出需要的日誌消息。總的來說,Qt日誌框架提供了一種簡潔、靈活和可配置的方法來管理和輸出日誌,有助於開發人員進行調試、錯誤排查以及日誌記錄等工作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章