g3log源代碼學習

g3log是一個高性能C++日誌庫,其代碼十分精簡和可讀性強,本文將從3個方面詳細介紹g3log源代碼學習。

一、g3log源代碼整體架構

g3log的整體架構十分清晰,其中有3個核心組件,分別是Logger、LogWorker和Sink。Logger負責產生日誌記錄,LogWorker是一個非同步的隊列,負責將Logger產生的日誌記錄進行處理和緩存,最終交由Sink進行輸出。

class Logger
{
public:
    Logger(const std::string& loggerId, SinkHandle worker, LogLevel minimumLevel)
    {
        ...
    }
    virtual ~Logger();

    void log(const LogMessage& message)
    {
        ...
    }

    ...
};
class LogWorker
{
public:
    ...
    LogWorker(std::string id, std::unique_ptr sink, const int& maxMessageSize, const int& workerCount);
    virtual ~LogWorker();

    inline int getWorkerId() const noexcept { return worker_id_; }
    void stop();
    void send(std::unique_ptr);
    bool try_send(std::unique_ptr);
    void sendImmediate(std::unique_ptr);

    template  inline void send(T&& message, const LEVELS& level)
    {
        send(LogMessage(std::forward(message), getWorkerId(), level), true);
    }

    ...
};
class Sink
{
public:
    virtual ~Sink() = default;
    virtual void sink(const LogMessage& message) = 0;
};

Logger、LogWorker、Sink三個組件各司其職,代碼規範且易於擴展。

二、日誌級別的控制和處理

g3log中有INFO、DEBUG、WARNING、ERROR和FATAL 5個級別的日誌等級,並且可以通過配置文件來設置日誌等級。在代碼中,對於每個日誌級別都有對應的宏定義,並且都會在編譯時進行一次條件判斷,從而確保了日誌輸出的高效性。

#define INFO_IF(instance, condition)                    \
    if (condition) {                                    \
        if (auto log_message = (instance).debug()) {     \
            log_message->write().startPrint().stream()

#define DEBUG_IF(instance, condition)                   \
    if (condition) {                                    \
        if (auto log_message = (instance).debug()) {     \
            log_message->write().startPrint().stream()

#define WARNING_IF(instance, condition)                 \
    if (condition) {                                    \
        if (auto log_message = (instance).warning()) {   \
            log_message->write().startPrint().stream()

#define ERROR_IF(instance, condition)                   \
    if (condition) {                                    \
        if (auto log_message = (instance).error()) {     \
            log_message->write().startPrint().stream()

#define FATAL_IF(instance, condition)                   \
    if (condition) {                                    \
        if (auto log_message = (instance).fatal()) {     \
            log_message->write().startPrint().stream()

代碼中對於每個宏定義都做了一次條件判斷,只有當日誌等級高於設置等級時,才會執行相應的日誌操作,從而提高了日誌輸出性能。

三、日誌輸出效率的提高

g3log的非同步輸出機制可以提高日誌系統的效率,其採用多個LogWorker來處理日誌記錄的緩存和輸出,而且每個LogWorker維護一個RingBuffer,多個LogWorker之間可以互相切換和傳輸RingBuffer,從而實現了多線程並發處理。

class RingBuffer
{
public:
    RingBuffer() { clear(); }

    void push_back(const T data)
    {
        auto slot = ++_tail & _mask;
        _buffer[slot] = data;
    }

    T pop_front()
    {
        auto slot = ++_head & _mask;
        return _buffer[slot];
    }

    ...
};

在實現RingBuffer時採用了循環隊列的設計,這樣一來從隊列頭和尾部的插入和刪除操作的處理速度就會非常快。

四、總結

通過對g3log源代碼的學習,我們可以發現g3log的設計非常簡單高效,代碼規範而且易於擴展和維護。同時,其採用了非同步輸出機制和多線程並發處理等機制,也提高了日誌系統的效率。

原創文章,作者:EZMXK,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/375558.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
EZMXK的頭像EZMXK
上一篇 2025-04-29 12:49
下一篇 2025-04-29 12:49

相關推薦

發表回復

登錄後才能評論