首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 實現高性能日誌系統 - 支援多級別、上下文信息、流式輸出

     編輯:關於C++

設計目標

參考 Unity Debug.Log 和 Qt qDebug() 風格,實現一個易用、高效的 C++ 日誌系統,滿足:

  1. 流式輸出支援多種數據類型(operator<< 鏈式調用)
  2. 日誌級別區分:Debug, Info, Warning, Error, Fatal
  3. 自動記錄文件名、函數名、行號
  4. 支援自定義類型與 STL 容器輸出

核心類架構

// 日誌上下文:文件、函數、行號
class MessageLogContext {
public:
    const char* file;
    const char* function;
    int line;
    MessageLogContext(const char* f, const char* fn, int l) 
        : file(f), function(fn), line(l) {}
};

// 前端介面:通過宏自動捕獲上下文
class MessageLogger {
    MessageLogContext ctx;
public:
    MessageLogger(const char* f, const char* fn, int l) : ctx(f, fn, l) {}
    Debug debug() const;    // 返回 Debug 對象,析構時自動輸出
    Debug info() const;
    Debug warning() const;
    Debug error() const;
    Debug fatal() const;
};

// 宏定義:使用時自動展開為 MessageLogger(__FILE__, __FUNCTION__, __LINE__).debug()
#define LOG_DEBUG MessageLogger(__FILE__, __FUNCTION__, __LINE__).debug()
#define LOG_INFO  MessageLogger(__FILE__, __FUNCTION__, __LINE__).info()
#define LOG_WARN  MessageLogger(__FILE__, __FUNCTION__, __LINE__).warning()
#define LOG_ERROR MessageLogger(__FILE__, __FUNCTION__, __LINE__).error()

Debug 類:流式輸出核心

class Debug {
    struct Stream {
        ostringstream ss;
        MessageLogContext ctx;
        LogType type;
        Stream() : type(LogType::Default) {}
        Stream(const MessageLogContext& c) : ctx(c), type(LogType::Default) {}
    };
    unique_ptr stream;
public:
    Debug() : stream(make_unique()) {}
    Debug(const MessageLogContext& ctx, LogType t) 
        : stream(make_unique(ctx)) { stream->type = t; }
    
    ~Debug() { flush(); }  // 析構時自動輸出
    
    // 通用流式輸出
    template
    Debug& operator<<(const T& val) {
        stream->ss << val;
        return *this;
    }
    
    // 支援 STL 容器
    template
    Debug& operator<<(const vector& vec) {
        stream->ss << '[';
        for (size_t i = 0; i < vec.size(); ++i) {
            stream->ss << vec[i];
            if (i + 1 < vec.size()) stream->ss << ", ";
        }
        stream->ss << ']';
        return *this;
    }
    
    void flush() {
        // 格式化輸出:[LEVEL] message (file:function:line)
        string prefix;
        switch(stream->type) {
            case LogType::Error:   prefix = "[ERROR] "; break;
            case LogType::Warning: prefix = "[WARN]  "; break;
            default: break;
        }
        cout << prefix << stream->ss.str() 
             << " (" << stream->ctx.file << ":" << stream->ctx.function 
             << ":" << stream->ctx.line << ")" << endl;
    }
};

MessageLogger 方法實現

Debug MessageLogger::debug() const {
    return Debug(ctx, LogType::Debug);
}
Debug MessageLogger::info() const {
    return Debug(ctx, LogType::Info);
}
Debug MessageLogger::warning() const {
    return Debug(ctx, LogType::Warning);
}
Debug MessageLogger::error() const {
    return Debug(ctx, LogType::Error);
}
Debug MessageLogger::fatal() const {
    return Debug(ctx, LogType::Fatal);
}

使用範例與輸出

struct Vec3 { float x, y, z; };
ostream& operator<<(ostream& os, const Vec3& v) {
    return os << "(" << v.x << ", " << v.y << ", " << v.z << ")";
}

void test() {
    vector vecs = {{1,2,3}, {4,5,6}};
    
    LOG_DEBUG << "Hello Debug";
    LOG_INFO  << "Vector: " << Vec3{1,2,3};
    LOG_WARN  << "Container: " << vecs;
    LOG_ERROR << "Error code: " << 404;
}

運行結果

Hello Debug (main.cpp:test:10)
[INFO] Vector: (1, 2, 3) (main.cpp:test:11)
[WARN]  Container: [(1, 2, 3), (4, 5, 6)] (main.cpp:test:12)
[ERROR] Error code: 404 (main.cpp:test:13)

關鍵設計亮點

  • RAII 自動刷新:Debug 臨時對象析構時自動輸出,無需手動調用 flush()
  • 宏捕獲上下文:__FILE__, __FUNCTION__, __LINE__ 自動傳遞
  • 模板支援任意類型:只需實現 operator<< 即可無縫接入
  • STL 容器專用重載:自動格式化輸出 vector, map 等
  • 零開銷抽象:發布版可通過宏禁用特定級別日誌
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved