最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++?spdlog?日志庫使用小結(jié)

 更新時(shí)間:2026年06月04日 10:26:56   作者:man_world  
spdlog是目前?C++?生態(tài)中性能最高(每秒可處理數(shù)百萬條消息)、使用最廣泛的現(xiàn)代日志庫之一,下面就來詳細(xì)的介紹下spdlog?日志庫使用,感興趣的可以了解一下

一、spdlog 簡介

spdlog: https://github.com/gabime/spdlog 是目前 C++ 生態(tài)中性能最高(每秒可處理數(shù)百萬條消息)、使用最廣泛的現(xiàn)代日志庫之一,支持 Linux、Windows、macOS、Android 等平臺,支持異步

它采用 Header-Only 設(shè)計(jì)(也可編譯為靜態(tài)庫),支持 C++11,線程安全,并提供極豐富的輸出目標(biāo)(Sink)與格式化能力

使用:

  • 直接 #include "spdlog/spdlog.h",無需鏈接庫,可以使用 PCH 預(yù)編譯大幅降低整個(gè)項(xiàng)目的編譯時(shí)間
  • ubuntu 上也可以使用 sudo apt install libspdlog-dev 安裝使用

核心概念及架構(gòu)圖如下:默認(rèn)日志等級是 info

  • Logger (日志記錄器):暴露給用戶的接口(如 logger->info(“…”))。它負(fù)責(zé)檢查日志等級,然后將消息分發(fā)給綁定的 Sink。
  • Sink (接收器):真正干活的實(shí)體。負(fù)責(zé)將格式化后的文本寫入目的地(控制臺、文件、網(wǎng)絡(luò)、甚至數(shù)據(jù)庫)。
  • Formatter (格式化器):決定日志的最終排版(時(shí)間、線程ID、文件名、消息本體)

┌─────────────────────────────────────────────────────────────┐
│                       spdlog 架構(gòu)圖                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  用戶代碼                                                    │
│    │                                                        │
│    ▼                                                        │
│ ┌─────────────┐      ┌───────────────────────┐              │
│ │   Logger     │ ───? │     Formatter         │              │
│ │ (日志記錄器) │      │ (格式化器:決定長啥樣) │              │
│ └──────┬──────┘      └───────────────────────┘              │
│        │                                                    │
│        │ (分發(fā)日志消息)                                      │
│        ▼                                                    │
│ ┌─────────────┐      ┌───────────────────────┐              │
│ │    Sink      │ ───? │     Destination       │              │
│ │ (日志接收器) │      │ (目標(biāo):控制臺/文件等)  │              │
│ └─────────────┘      └───────────────────────┘              │
│                                                             │
│ 注:一個(gè) Logger 可以綁定 多個(gè) Sink(實(shí)現(xiàn)同時(shí)輸出到屏幕和文件) │
└─────────────────────────────────────────────────────────────┘

二、spdlog 使用指南

2.1、基礎(chǔ)日志輸出(宏 vs API)

  • 要想顯示文件名、行號、函數(shù)名,必須使用宏的方式調(diào)用 SPDLOG_DEBUG 且文件最開始 #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE
  • 宏自動(dòng)展開為 SPDLOG_LOGGER_CALL(spdlog::default_logger(), spdlog::level::info, ...),自帶上下文信息
// define SPDLOG_ACTIVE_LEVEL to one of those (before including spdlog.h):
// SPDLOG_LEVEL_TRACE,
// SPDLOG_LEVEL_DEBUG,
// SPDLOG_LEVEL_INFO,
// SPDLOG_LEVEL_WARN,
// SPDLOG_LEVEL_ERROR,
// SPDLOG_LEVEL_CRITICAL,
// SPDLOG_LEVEL_OFF

// 兼容舊版本宏
// #define LOG_INFO(...)  SPDLOG_INFO(__VA_ARGS__)
// #define LOG_DEBUG(...) SPDLOG_DEBUG(__VA_ARGS__)
// #define LOG_WARN(...)  SPDLOG_WARN(__VA_ARGS__)
// #define LOG_ERROR(...) SPDLOG_ERROR(__VA_ARGS__)


#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE
#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"

int main() {
    // 創(chuàng)建彩色控制臺 Logger(多線程安全)
    auto console = spdlog::stdout_color_mt("console");
    spdlog::set_default_logger(console);

    // ? 宏方式:自動(dòng)攜帶文件名/行號/函數(shù)名,推薦生產(chǎn)使用
    SPDLOG_INFO("Server started on port {}", 8080);
    SPDLOG_ERROR("Failed to open config: {}", "config.yaml");

    // ? API 方式:更靈活,適合封裝或動(dòng)態(tài)級別
    spdlog::debug("User {} logged in from {}", "alice", "192.168.1.5");
    spdlog::warn("Disk usage: {:.2f}%", 87.5);

    return 0;
}

// 輸出如下所示
[2026-04-23 09:30:15.380] [console] [info] [main.cpp:11] Server started on port 8080
[2026-04-23 09:30:15.380] [console] [error] [main.cpp:12] Failed to open config: config.yaml
[2026-04-23 09:30:15.380] [console] [warning] Disk usage: 87.50%


// 更多格式控制
SPDLOG_WARN("Easy padding in numbers like {:08d}", 12);
SPDLOG_CRITICAL("Support for int: {0:d};  hex: {0:x};  oct: {0:o}; bin: {0:b}", 42);
SPDLOG_INFO("Support for floats {:03.2f}", 1.23456);
SPDLOG_INFO("Positional args are {1} {0}..", "too", "supported");
SPDLOG_INFO("{:>30}", "right aligned");

// 輸出如下所示
[2026-04-23 14:48:37] [warning] [main.cpp:52] Easy padding in numbers like 00000012
[2026-04-23 14:48:37] [critical] [main.cpp:53] Support for int: 42;  hex: 2a;  oct: 52; bin: 101010
[2026-04-23 14:48:37] [info] [main.cpp:54] Support for floats 1.23
[2026-04-23 14:48:37] [info] [main.cpp:55] Positional args are supported too..
[2026-04-23 14:48:37] [info] [main.cpp:56]                  right aligned

2.2、日志級別控制

  • 設(shè)置日志級別
/*** 日志級別,默認(rèn) info
trace   // 最細(xì)
debug
info
warn
err
critical
off     // 關(guān)閉
***/

// 全局級別
spdlog::set_level(spdlog::level::debug);

// 單個(gè) Logger 級別
console->set_level(spdlog::level::warn);



// 編譯期過濾(大幅提升 Release 性能)
// 必須在 #include <spdlog/spdlog.h> 之前定義
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO
#include "spdlog/spdlog.h"
  • 獲取日志級別
// 獲取默認(rèn)日志器的當(dāng)前等級
spdlog::level::level_enum current_level = spdlog::get_level();

// 轉(zhuǎn)換為字符串輸出
SPDLOG_WARN("Current Log level: {}", spdlog::level::to_string_view(current_level));
  • 從環(huán)境變量更改日志級別
#include "spdlog/cfg/env.h"
int main (int argc, char *argv[])
{
    // 主函數(shù)中:從環(huán)境變量 SPDLOG_LEVEL 讀取并應(yīng)用等級
    spdlog::cfg::load_env_levels();
    // or specify the env variable name:
    // MYAPP_LEVEL=info,mylogger=trace && ./example
    // spdlog::cfg::load_env_levels("MYAPP_LEVEL");
    
    // or from the command line:
    // ./example SPDLOG_LEVEL=info,mylogger=trace
    
    // #include "spdlog/cfg/argv.h" // for loading levels from argv
    // spdlog::cfg::load_argv_levels(argc, argv);
}


// 設(shè)置環(huán)境變量更改日志級別包含自定義日志等級 (trace<debug<info<warn<err<critical<off)
export SPDLOG_LEVEL=info,mylogger=trace
./example


// 以下都是有效的(不區(qū)分大小寫)
export SPDLOG_LEVEL=trace      // 最詳細(xì)
export SPDLOG_LEVEL=debug      // 調(diào)試
export SPDLOG_LEVEL=info       // 信息
export SPDLOG_LEVEL=warn       // 警告
export SPDLOG_LEVEL=warning    // 警告(完整拼寫)
export SPDLOG_LEVEL=error      // 錯(cuò)誤
export SPDLOG_LEVEL=err        // 錯(cuò)誤(簡寫)
export SPDLOG_LEVEL=critical   // 嚴(yán)重錯(cuò)誤
export SPDLOG_LEVEL=off        // 關(guān)閉

//  以下都會(huì)返回 level::off(關(guān)閉文件日志)spdlog::level::from_str(file_level_str) 
export SPDLOG_LEVEL=test
export SPDLOG_LEVEL=foo
export SPDLOG_LEVEL=123
export SPDLOG_LEVEL=""
  • 控制日志級別輸出不同的內(nèi)容
// 1、export SPDLOG_LEVEL=err 最少日志顯示,輸出致命錯(cuò)誤,程序中斷

// 2、export SPDLOG_LEVEL=info(默認(rèn) Release 版本使用) 
// 可以輸出關(guān)于設(shè)備的基本信息、SDK 版本號等信息,也會(huì)輸出算法內(nèi)部發(fā)生錯(cuò)誤時(shí)針對性的反饋信息

// 3、export SPDLOG_LEVEL=debug 調(diào)試日志輸出
// 可以輸出關(guān)于模型的基本信息,比如模型輸入/輸出tensor的維度、對齊方式、步長、數(shù)據(jù)類型等,
// 由于芯片種類較多,每種芯片移植的差異較大,同一模型在不同芯片上獲取到的信息都不盡相同,日志功能可以將這些信息詳細(xì)打印出來

// 4、export SPDLOG_LEVEL=trace 最詳細(xì)調(diào)試日志輸出
// 可保存模型 forward 前后的輸入、輸出tensor到文件中,
// 輸入是圖像的話會(huì)保存成相應(yīng)圖像格式
// 輸出一般保存成 float 格式文件,以 CH*W 方式存儲,這里主要是為了方便與浮點(diǎn)模型進(jìn)行對比分析,排查模型精度問題


// auto logger = spdlog::default_logger();   // 獲取默認(rèn)的 logger
if (spdlog::should_log(spdlog::level::trace)) {
    // 只有 trace 級別及以上時(shí),才執(zhí)行這個(gè)開銷大的操作
    SPDLOG_TRACE("goto trace");
}

if (spdlog::should_log(spdlog::level::debug)) {
    // 只有 debug 級別及以上時(shí),才執(zhí)行這個(gè)開銷大的操作
    SPDLOG_DEBUG("goto debug");
}

if (spdlog::should_log(spdlog::level::info)) {
    // 只有 info 級別及以上時(shí),才執(zhí)行這個(gè)開銷大的操作
    SPDLOG_INFO("goto info");
}


if (logger->level() <= spdlog::level::debug) {
    // 當(dāng)前允許 debug
}



// 運(yùn)行時(shí)在程序里動(dòng)態(tài)修改日志等級
spdlog::set_level(spdlog::level::debug);

算法執(zhí)行過程中,通過外部操作改變?nèi)罩据敵龅燃?/strong>

// 方案一:信號控制(SIGUSR1/SIGUSR2)
// 適用場景:本地調(diào)試、單機(jī)服務(wù)、快速切換
// 原理:通過 kill -USR1 <pid> 動(dòng)態(tài)升降日志等級,無需重啟進(jìn)程
// kill -USR1 <pid>  # 日志變詳細(xì) (debug -> trace)
// kill -USR2 <pid>  # 日志變粗略 (info -> warn)
#include <csignal>
#include <atomic>
#include <thread>
#include "spdlog/spdlog.h"

// ?? 全局原子標(biāo)志(信號處理函數(shù)只能做 async-signal-safe 操作)
std::atomic<int> signal_flag{0}; // 0=無操作, 1=升級, 2=降級

void signal_handler(int signum) {
    if (signum == SIGUSR1) signal_flag.store(1);
    else if (signum == SIGUSR2) signal_flag.store(2);
}

//  后臺控制線程
void start_signal_logger_control() {
    struct sigaction sa{};
    sa.sa_handler = signal_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    sigaction(SIGUSR1, &sa, nullptr);
    sigaction(SIGUSR2, &sa, nullptr);

    std::thread([]() {
        while (true) {
            int flag = signal_flag.exchange(0); // 原子讀取并清零
            if (flag == 0) {
                std::this_thread::sleep_for(std::chrono::milliseconds(100));
                continue;
            }

            auto current = spdlog::default_logger()->level();
            spdlog::level::level_enum new_level = current;

            if (flag == 1 && current > spdlog::level::trace) {
                new_level = static_cast<spdlog::level::level_enum>(current - 1); // 升級(更詳細(xì))
            } else if (flag == 2 && current < spdlog::level::off) {
                new_level = static_cast<spdlog::level::level_enum>(current + 1); // 降級(更粗略)
            }

            spdlog::set_level(new_level);
            spdlog::info("?? Log level changed to: {}", spdlog::level::to_string_view(new_level));
        }
    }).detach();
}

// ? 算法代碼完全不變
void run_algorithm() {
    SPDLOG_DEBUG("Expensive debug data: {}", compute_debug_info());
    SPDLOG_INFO("Algorithm step {}", get_step());
}


//  方案二:配置文件熱加載(生產(chǎn)推薦)
// 適用場景:自動(dòng)化運(yùn)維、K8s ConfigMap、結(jié)構(gòu)化控制
// 原理:后臺線程定期輪詢或監(jiān)聽配置文件,解析 log_level 字段并應(yīng)用
#include <fstream>
#include <filesystem>
#include <thread>
#include <nlohmann/json.hpp> // 示例用 json,也可用 yaml/ini
#include "spdlog/spdlog.h"

namespace fs = std::filesystem;

void start_config_watcher(const std::string& config_path) {
    std::thread([config_path]() {
        fs::file_time_type last_mod = fs::last_write_time(config_path);
        
        while (true) {
            std::this_thread::sleep_for(std::chrono::seconds(2));
            
            auto current_mod = fs::last_write_time(config_path);
            if (current_mod == last_mod) continue;
            last_mod = current_mod;

            try {
                std::ifstream file(config_path);
                nlohmann::json cfg = nlohmann::json::parse(file);
                std::string level_str = cfg.value("log_level", "info");
                
                auto new_level = spdlog::level::from_str(level_str);
                if (new_level != spdlog::level::off) {
                    spdlog::set_level(new_level);
                    spdlog::info("?? Config reloaded: log_level = {}", level_str);
                }
            } catch (const std::exception& e) {
                spdlog::warn("Failed to parse config: {}", e.what());
            }
        }
    }).detach();
}

// 配置文件示例 (logger.json):修改 JSON 后保存,2 秒內(nèi)自動(dòng)生效
{
  "log_level": "debug",
  "sink_config": { ... }
}


// 方案三:網(wǎng)絡(luò)/Admin 接口(遠(yuǎn)程運(yùn)維)
// 適用場景:分布式集群、遠(yuǎn)程調(diào)試、CI/CD 集成
// 原理:啟動(dòng)一個(gè)輕量 TCP/HTTP 服務(wù),接收指令如 SET_LEVEL debug
// 遠(yuǎn)程操作:echo "SET_LEVEL trace" | nc 127.0.0.1 8888
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <thread>
#include <cstring>
#include "spdlog/spdlog.h"

void start_admin_server(uint16_t port) {
    std::thread([port]() {
        int server_fd = socket(AF_INET, SOCK_STREAM, 0);
        sockaddr_in addr{};
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = INADDR_ANY;
        addr.sin_port = htons(port);
        bind(server_fd, (sockaddr*)&addr, sizeof(addr));
        listen(server_fd, 5);

        while (true) {
            int client_fd = accept(server_fd, nullptr, nullptr);
            char buf[128];
            int n = read(client_fd, buf, sizeof(buf)-1);
            if (n > 0) {
                buf[n] = '\0';
                std::string cmd(buf);
                
                // 簡單協(xié)議: SET_LEVEL <level>
                if (cmd.rfind("SET_LEVEL ", 0) == 0) {
                    std::string level_str = cmd.substr(10);
                    auto lvl = spdlog::level::from_str(level_str);
                    if (lvl != spdlog::level::off) {
                        spdlog::set_level(lvl);
                        write(client_fd, "OK\n", 3);
                        spdlog::info(" Admin: level -> {}", level_str);
                    } else {
                        write(client_fd, "INVALID_LEVEL\n", 14);
                    }
                }
            }
            close(client_fd);
        }
    }).detach();
}

2.3、輸出格式控制

// 默認(rèn)格式:[時(shí)間] [級別] [線程] 消息
spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [%t] %v");  // // %^%$ 包裹級別實(shí)現(xiàn)彩色

// 帶源碼位置:去掉毫秒,增加源文件:行號
spdlog::set_pattern("[%Y-%m-%d %H:%M:%S] [%^%l%$] [%s:%#] %v");

// 增加線程 ID
spdlog::set_pattern("[%Y-%m-%d %H:%M:%S] [%^%l%$] [%s:%#] [%t] %v");

2.4、常用 Sink(輸出目標(biāo))

#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/syslog_sink.h"
#include "spdlog/sinks/dist_sink.h"

// 1. 基礎(chǔ)文件(追加模式)
auto file_logger = spdlog::basic_logger_mt("file", "app.log");

// 2. 按大小輪轉(zhuǎn)(最大 5MB,保留 3 個(gè)備份)
auto rotating = spdlog::rotating_logger_mt("rotating", "logs/app.log", 5*1024*1024, 3);

// 3. 按天輪轉(zhuǎn)(每天 02:30 切割)
auto daily = spdlog::daily_logger_mt("daily", "logs/app.log", 2, 30);

// 4. 多路分發(fā)(同時(shí)輸出到控制臺 + 文件)
spdlog::sinks::dist_sink_mt dist_sink;
dist_sink.add_sink(std::make_shared<spdlog::sinks::stdout_color_sink_mt>());
dist_sink.add_sink(std::make_shared<spdlog::sinks::rotating_file_sink_mt>("logs/dist.log", 10*1024*1024, 5));
auto multi_logger = std::make_shared<spdlog::logger>("multi", dist_sink);
spdlog::register_logger(multi_logger);

2.5、異步日志(高并發(fā)必備)

#include "spdlog/spdlog.h"           // ? 主頭文件,必須包含
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/async.h"            // ? 異步日志必需

int main() {
    // 1?? 初始化異步線程池(可選,但推薦)
    spdlog::init_thread_pool(8192, 1);

    // 2?? 創(chuàng)建異步 logger
    auto logger = spdlog::create_async<spdlog::sinks::rotating_file_sink_mt>(
        "async_file", "logs/app.log", 10*1024*1024, 3);

    spdlog::set_default_logger(logger);

    // 3?? 業(yè)務(wù)日志
    SPDLOG_INFO("Application started");

    // 4?? ? 程序退出前必須調(diào)用,確保異步隊(duì)列清空
    spdlog::shutdown(); 

    return 0;
}

// 方案1:cmakelists 中添加 -pthread 編譯/鏈接標(biāo)志
# ? 同時(shí)添加編譯和鏈接標(biāo)志(-pthread 影響預(yù)處理、編譯、鏈接三階段)
target_compile_options(log2 PRIVATE -pthread)
target_link_options(log2 PRIVATE -pthread)

// 方案2:使用 Threads::Threads(推薦,跨平臺)
# 1?? 查找系統(tǒng)線程庫(自動(dòng)處理 -pthread 標(biāo)志)
find_package(Threads REQUIRED)

# 4?? ?? 關(guān)鍵:鏈接線程庫
target_link_libraries(log2 PRIVATE Threads::Threads)

2.6、錯(cuò)誤處理與回調(diào)

// 自定義日志寫入失敗處理(如磁盤滿、權(quán)限不足)
spdlog::set_error_handler([](const std::string& msg) {
    std::cerr << "[SPDLOG ERROR] " << msg << std::endl;
    // 可在此處觸發(fā)告警、 fallback 到控制臺等
});

2.7、android 示例

#include "spdlog/sinks/android_sink.h"
void android_example()
{
    std::string tag = "spdlog-android";
    auto android_logger = spdlog::android_logger_mt("android", tag);
    android_logger->critical("Use \"adb shell logcat\" to view this message.");
}

三、spdlog 實(shí)戰(zhàn)函數(shù)封裝使用

  • 實(shí)際日志需求示例:
    • 默認(rèn)日志等級為 info,可以通過環(huán)境變量 SPDLOG_LEVEL 改變系統(tǒng)日志等級,SPDLOG_LEVEL_FILE 改變文件日志等級(默認(rèn)關(guān)閉),打開的時(shí)候會(huì)在當(dāng)前目錄下創(chuàng)建 logs/app.log 文件
    • 可判斷當(dāng)前日志等級,從而完成不同等級的 debug 操作(通過環(huán)境變量改變?nèi)罩镜燃夁M(jìn)行 debug
    • 通過宏的方式調(diào)用,會(huì)顯示源文件的名稱及行號
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE  // 開發(fā)/調(diào)試環(huán)境,編譯時(shí)過濾,如果設(shè)置成 INFO,那么 SPDLOG_TRACE、SPDLOG_DEBUG 宏被編譯優(yōu)化掉
// #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO  // 生產(chǎn)環(huán)境: 只保留 info 及以上,這樣出現(xiàn)問題就沒辦法調(diào)試了(極致性能優(yōu)化的時(shí)候可以開啟) 
#include "spdlog/spdlog.h"
#include "spdlog/cfg/env.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"  // 彩色控制臺


void init_logger() {
    // 1、構(gòu)建 sinks 列表(sink 的默認(rèn)等級是 trace 最低等級)
    std::vector<spdlog::sink_ptr> sinks;

    // 2、控制臺 multi-threaded sink:彩色輸出,支持 ANSI/Windows(始終添加)
    auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
    // console_sink->set_level(spdlog::level::debug);  // 控制臺:僅 debug 及以上
    sinks.push_back(console_sink);

    // 3、文件 sink(按需添加):生產(chǎn)環(huán)境默認(rèn)關(guān)閉文件日志(也不生成文件),調(diào)試環(huán)境可以設(shè)置為 trace,記錄所有(生成日志文件)
    // 3.1、從環(huán)境變量讀取配置,設(shè)置文件默認(rèn)日志等級,默認(rèn)關(guān)閉
    const char *file_level_str = std::getenv("SPDLOG_LEVEL_FILE");
    spdlog::level::level_enum file_level = spdlog::level::off;

    // 3.2、環(huán)境變量已設(shè)置,嘗試解析
    if (file_level_str) {
        // 傳入的字符串如果都不匹配(trace<debug<info<warn<err<critical<off),返回 level::off
        file_level = spdlog::level::from_str(file_level_str);
    }

    // 3.3、當(dāng)外部設(shè)置了文件日志等級時(shí)才創(chuàng)建 log 文件
    if (file_level != spdlog::level::off) {
        // 1?文件 multi-threaded sink:按大小輪轉(zhuǎn),5MB/文件,保留 3 個(gè)歷史備份文件,總文件數(shù)最多為 4 個(gè)
        // app.log(當(dāng)前正在寫入); app.log.1(最新的備份); app.log.2; app.log.3(最老的備份)
        // 當(dāng)新的 app.log 再次達(dá)到 5MB 時(shí),會(huì)刪除最老的備份,并對其它的進(jìn)行日志進(jìn)行重命名
        auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(
            "logs/app.log", 5 * 1024 * 1024, 3);
        file_sink->set_level(file_level); // 文件:
        sinks.push_back(file_sink);
    }

    // 4、創(chuàng)建 logger,綁定 sinks 中的所有 sink
    auto logger = std::make_shared<spdlog::logger>("global_log_file",
                                                   sinks.begin(),
                                                   sinks.end());

    // 5、全局格式與默認(rèn)設(shè)置
    // 一條日志要被輸出,必須同時(shí)滿足:日志等級 >= logger->level() 且 日志等級 >= sink->level()
    logger->set_pattern("[%Y-%m-%d %H:%M:%S] [%^%l%$] [%s:%#] %v"); // %^%$ 包裹級別實(shí)現(xiàn)彩色
    logger->set_level(spdlog::level::info); // logger 總開關(guān)
    logger->flush_on(spdlog::level::warn); // warn 及以上立即刷新
    // spdlog::flush_every(std::chrono::seconds(3));  // 設(shè)置刷新間隔

    // 6、設(shè)為默認(rèn) logger,全局生效(不注冊到全局表,避免日志命名沖突)
    spdlog::set_default_logger(logger);
    // 不通過 spdlog::get("name") 按名獲取,完全可以跳過 register_logger
    // spdlog::register_logger(logger); // 可選,便于按名獲取

    // 7、從環(huán)境變量 SPDLOG_LEVEL 讀取并應(yīng)用等級; export SPDLOG_LEVEL=debug 調(diào)試
    // 調(diào)用時(shí)機(jī):必須在創(chuàng)建 logger 并注冊后、業(yè)務(wù)日志打印前調(diào)用
    spdlog::cfg::load_env_levels();

    // 8、獲取默認(rèn)日志器的當(dāng)前等級并打印日志等級
    spdlog::level::level_enum sys_level = spdlog::get_level();
    // 宏在預(yù)處理期自動(dòng)展開為:spdlog::log(spdlog::source_loc{__FILE__, __LINE__, SPDLOG_FUNCTION}, level, fmt, args...)
    SPDLOG_WARN("Current Sys Log level: {}", spdlog::level::to_string_view(sys_level));
    SPDLOG_WARN("Current File Log level: {}", spdlog::level::to_string_view(file_level));
    SPDLOG_INFO("Logger initialized successfully.");
    SPDLOG_INFO("********************************");
}


int main() {
    // 初始化日志管理
    init_logger();

    SPDLOG_WARN("Easy padding in numbers like {:08d}", 12);
    SPDLOG_CRITICAL("Support for int: {0:d};  hex: {0:x};  oct: {0:o}; bin: {0:b}", 42);
    SPDLOG_INFO("Support for floats {:03.2f}", 1.23456);
    SPDLOG_INFO("Positional args are {1} {0}..", "too", "supported");
    SPDLOG_INFO("{:>30}", "right aligned");
    SPDLOG_DEBUG("This message should be displayed..");
    SPDLOG_TRACE("Some trace message with param {}", 42);

    // auto logger = spdlog::default_logger();   // 獲取默認(rèn)的 logger
    if (spdlog::should_log(spdlog::level::trace)) {
        // 只有 trace 級別及以上時(shí),才執(zhí)行這個(gè)開銷大的操作
        SPDLOG_TRACE("goto trace");
    }

    if (spdlog::should_log(spdlog::level::debug)) {
        // 只有 debug 級別及以上時(shí),才執(zhí)行這個(gè)開銷大的操作
        SPDLOG_DEBUG("goto debug");
    }

    if (spdlog::should_log(spdlog::level::info)) {
        // 只有 info 級別及以上時(shí),才執(zhí)行這個(gè)開銷大的操作
        SPDLOG_INFO("goto info");
    }
}



// 輸出示例如下:
[2026-04-23 17:26:16] [warning] [main.cpp:62] Current Sys Log level: info
[2026-04-23 17:26:16] [warning] [main.cpp:63] Current File Log level: off
[2026-04-23 17:26:16] [info] [main.cpp:64] Logger initialized successfully.
[2026-04-23 17:26:16] [info] [main.cpp:65] ********************************
[2026-04-23 17:26:16] [warning] [main.cpp:73] Easy padding in numbers like 00000012
[2026-04-23 17:26:16] [critical] [main.cpp:74] Support for int: 42;  hex: 2a;  oct: 52; bin: 101010
[2026-04-23 17:26:16] [info] [main.cpp:75] Support for floats 1.23
[2026-04-23 17:26:16] [info] [main.cpp:76] Positional args are supported too..
[2026-04-23 17:26:16] [info] [main.cpp:77]                  right aligned
[2026-04-23 17:26:16] [info] [main.cpp:94] goto info

  • CmkeList.txt 示例
cmake_minimum_required(VERSION 4.1)
project(log)

set(CMAKE_CXX_STANDARD 17)

# Debug 模式:啟用所有日志(極致優(yōu)化的時(shí)候添加,編譯期過濾日志級別)
# add_compile_definitions(SPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_INFO)
#if(CMAKE_BUILD_TYPE STREQUAL "Debug")
#    add_definitions(-DSPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_TRACE)
#else()
#    # Release 模式:只啟用 info 及以上
#    add_definitions(-DSPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_INFO) # 把 INFO 以下的宏全部變成空代碼
#endif()

add_executable(log main.cpp)

target_include_directories(log PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
message(STATUS "Include path: ${CMAKE_CURRENT_SOURCE_DIR}")

# 異步需添加:查找系統(tǒng)線程庫(自動(dòng)處理 -pthread 標(biāo)志)
find_package(Threads REQUIRED)

# 異步需添加:鏈接線程庫
target_link_libraries(log2 PRIVATE Threads::Threads)
  • cmake 編譯與構(gòu)建命令
# 清理舊的 Debug 構(gòu)建目錄
rm -rf cmake-build-debug
# 重新配置,指定 Debug 模式
cmake -B cmake-build-debug -S . -DCMAKE_BUILD_TYPE=Debug
# 構(gòu)建
cmake --build cmake-build-debug
# 清理舊的 Release 構(gòu)建目錄
rm -rf cmake-build-release
# 重新配置,指定 Release 模式
cmake -B cmake-build-release -S . -DCMAKE_BUILD_TYPE=Release
# 構(gòu)建
cmake --build cmake-build-release

到此這篇關(guān)于C++ spdlog 日志庫使用小結(jié)的文章就介紹到這了,更多相關(guān)C++ spdlog 日志庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

  • C語言從猜數(shù)字游戲中理解數(shù)據(jù)結(jié)構(gòu)

    C語言從猜數(shù)字游戲中理解數(shù)據(jù)結(jié)構(gòu)

    猜數(shù)字是興起于英國的益智類小游戲,起源于20世紀(jì)中期,一般由兩個(gè)人或多人玩,也可以由一個(gè)人和電腦玩。游戲規(guī)則為一方出數(shù)字,一方猜,今天我們來用這個(gè)游戲案例理解數(shù)據(jù)結(jié)構(gòu)
    2022-04-04
  • Pipes實(shí)現(xiàn)LeetCode(192.單詞頻率)

    Pipes實(shí)現(xiàn)LeetCode(192.單詞頻率)

    這篇文章主要介紹了Pipes實(shí)現(xiàn)LeetCode(192.單詞頻率),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • vscode刷acm、leetcode的題目

    vscode刷acm、leetcode的題目

    vscode是一款越來越受碼農(nóng)們喜愛的軟件,大多數(shù)人學(xué)習(xí)編程繞不開的一部分就是算法,很多人都喜歡刷LeetCode的題目,本文就來介紹一下
    2021-06-06
  • C語言堆棧入門指南

    C語言堆棧入門指南

    我身邊的一些編程的朋友以及在網(wǎng)上看帖遇到的朋友中有好多也說不清堆棧,所以我想有必要給大家分享一下我對堆棧的看法,有說的不對的地方請朋友們不吝賜教,這對于大家學(xué)習(xí)會(huì)有很大幫助
    2014-01-01
  • C語言實(shí)現(xiàn)簡單的推箱子小游戲

    C語言實(shí)現(xiàn)簡單的推箱子小游戲

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)簡單的推箱子小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • C語言算法積累加tag的循環(huán)隊(duì)列

    C語言算法積累加tag的循環(huán)隊(duì)列

    這篇文章主要為大家介紹了C語言算法積累加tag的循環(huán)隊(duì)列的解題思路,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • 深入理解Qt信號槽機(jī)制

    深入理解Qt信號槽機(jī)制

    信號槽是 Qt 框架引以為豪的機(jī)制之一。本文主要介紹了Qt信號槽機(jī)制,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • C語言輸出孿生素?cái)?shù)的實(shí)現(xiàn)示例

    C語言輸出孿生素?cái)?shù)的實(shí)現(xiàn)示例

    本文主要介紹了C語言輸出孿生素?cái)?shù)的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • C++ decltype類型說明符

    C++ decltype類型說明符

    在C++中,decltype作為操作符,用于查詢表達(dá)式的數(shù)據(jù)類型。decltype在C++11標(biāo)準(zhǔn)制定時(shí)引入,主要是為泛型編程而設(shè)計(jì),以解決泛型編程中,由于有些類型由模板參數(shù)決定,而難以(甚至不可能)表示之的問題。
    2016-03-03
  • C++實(shí)現(xiàn)T型插補(bǔ)詳解

    C++實(shí)現(xiàn)T型插補(bǔ)詳解

    這篇文章主要介紹了C++實(shí)現(xiàn)T型插補(bǔ),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-10-10

最新評論

吉木萨尔县| 仲巴县| 巢湖市| 于田县| 广丰县| 陆河县| 白朗县| 扶绥县| 溧阳市| 静海县| 清丰县| 安徽省| 明星| 巨野县| 辽宁省| 靖西县| 鲜城| 阳新县| 南投市| 日喀则市| 湄潭县| 五莲县| 清河县| 镇赉县| 法库县| 界首市| 新密市| 上栗县| 安阳县| 安顺市| 三台县| 永定县| 焦作市| 大安市| 山东| 阿勒泰市| 施秉县| 留坝县| 石屏县| 师宗县| 阳新县|