news 2026/1/22 11:55:23

spdlog 库下载,编译,并使用的例子

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
spdlog 库下载,编译,并使用的例子

文章目录

    • 一、下载 spdlog
      • 方法1:使用包管理器(推荐)
      • 方法2:手动下载
    • 二、编译 spdlog
      • 使用 CMake 编译
      • 编译选项
    • 三、在项目中使用
      • CMake 项目集成
      • 简单使用示例
    • 四、编译示例程序
    • 五、依赖要求
    • 注意事项
    • 一、环境准备
      • 1. 安装编译工具
      • 2. 获取 spdlog 源代码
    • 二、使用 CMake 生成不同配置
      • 方法1:使用批处理脚本(推荐)
      • 方法2:手动命令编译
    • 三、完整的编译脚本
    • 四、单独编译各版本命令
      • 编译 x64 Debug
      • 编译 x64 Release
      • 编译 Win32 Debug
      • 编译 Win32 Release
    • 五、打包为可分发库
    • 六、使用注意事项
      • 1. 编译器版本对应关系
      • 2. 文件命名规则
      • 3. 在项目中使用
  • 使用例子
  • 完整的 spdlog 使用示例
    • 项目结构
    • 1. CMakeLists.txt
    • 2. logger_config.h - 日志配置类
    • 3. logger_config.cpp
    • 4. main.cpp - 主程序示例
    • 5. advanced_logging.cpp - 高级功能演示
    • 6. 编译和运行
      • Windows (MSVC):
      • Linux/Mac:
    • 7. 示例输出
    • 8. 主要特点

一、下载 spdlog

方法1:使用包管理器(推荐)

vcpkg:

vcpkginstallspdlog

Conan:

conaninstallspdlog/1.x.x@

APT (Ubuntu/Debian):

sudoapt-getinstalllibspdlog-dev

方法2:手动下载

Git Clone:

gitclone https://github.com/gabime/spdlog.gitcdspdlog# 切换到稳定版本gitcheckout v1.x.x

直接下载 ZIP:
访问 https://github.com/gabime/spdlog 下载最新版本

二、编译 spdlog

spdlog 是 header-only 库,但如果你需要编译为动态/静态库:

使用 CMake 编译

# 克隆仓库gitclone https://github.com/gabime/spdlog.gitcdspdlog# 创建构建目录mkdirbuild&&cdbuild# 配置 CMakecmake..-DCMAKE_BUILD_TYPE=Release# 编译cmake --build.--config Release# 安装(可选)sudocmake --install.

编译选项

# 指定编译为静态库cmake..-DSPDLOG_BUILD_SHARED=OFF# 编译并运行测试cmake..-DSPDLOG_BUILD_TESTS=ON cmake --build.--targettest# 编译示例cmake..-DSPDLOG_BUILD_EXAMPLE=ON# 指定安装路径cmake..-DCMAKE_INSTALL_PREFIX=/usr/local

三、在项目中使用

CMake 项目集成

方法1:find_package(如果已安装)

find_package(spdlog REQUIRED) target_link_libraries(your_target PRIVATE spdlog::spdlog)

方法2:添加为子模块

add_subdirectory(spdlog) target_link_libraries(your_target PRIVATE spdlog::spdlog)

方法3:FetchContent(CMake 3.11+)

include(FetchContent) FetchContent_Declare( spdlog GIT_REPOSITORY "https://github.com/gabime/spdlog.git" GIT_TAG "v1.x.x" ) FetchContent_MakeAvailable(spdlog) target_link_libraries(your_target PRIVATE spdlog::spdlog)

简单使用示例

#include<spdlog/spdlog.h>#include<spdlog/sinks/basic_file_sink.h>intmain(){// 基础使用spdlog::info("Hello, {}!","World");spdlog::warn("This is a warning");// 创建文件日志autofile_logger=spdlog::basic_logger_mt("file_logger","logs.txt");file_logger->info("File log message");// 设置日志级别spdlog::set_level(spdlog::level::debug);return0;}

四、编译示例程序

CMakeLists.txt:

cmake_minimum_required(VERSION 3.10) project(SpdlogExample) set(CMAKE_CXX_STANDARD 17) # 方法1:如果spdlog在子目录 add_subdirectory(spdlog) # 方法2:如果已安装 find_package(spdlog REQUIRED) add_executable(example main.cpp) target_link_libraries(example PRIVATE spdlog::spdlog)

编译命令:

mkdirbuild&&cdbuild cmake..make./example

五、依赖要求

  • C++11 或更高版本
  • 推荐 CMake 3.10+
  • 可选依赖(用于额外功能):
    • fmt(格式化库)
    • pthread(多线程支持)

注意事项

  1. 头文件版本:spdlog 是 header-only 库,可以直接复制头文件使用
  2. 跨平台:支持 Windows、Linux、macOS
  3. 性能:默认是线程安全的,支持异步日志
  4. 编译时间:由于是模板库,编译时间可能较长,可以使用预编译头文件优化

选择哪种方式取决于你的项目需求。对于简单项目,直接包含头文件即可;对于大型项目,建议使用包管理器或 CMake 集成。

我来为您详细介绍如何编译 x64 和 Win32 的 Debug/Release 版本的 spdlog 库。

一、环境准备

1. 安装编译工具

# 1. 安装 Visual Studio (确保包含 C++ 开发组件)# 2. 安装 CMake: https://cmake.org/download/# 3. 可选: 安装 vcpkg 用于依赖管理

2. 获取 spdlog 源代码

gitclone https://github.com/gabime/spdlog.gitcdspdlog

二、使用 CMake 生成不同配置

方法1:使用批处理脚本(推荐)

create_builds.bat:

@echo off setlocal enabledelayedexpansion set SPDLOG_DIR=%cd% set GENERATOR="Visual Studio 17 2022" REM 创建所有构建目录 mkdir build_x64_debug 2>nul mkdir build_x64_release 2>nul mkdir build_win32_debug 2>nul mkdir build_win32_release 2>nul echo 生成 x64 Debug 配置... cd build_x64_debug cmake %SPDLOG_DIR% -G %GENERATOR% -A x64 -DCMAKE_BUILD_TYPE=Debug cd .. echo 生成 x64 Release 配置... cd build_x64_release cmake %SPDLOG_DIR% -G %GENERATOR% -A x64 -DCMAKE_BUILD_TYPE=Release cd .. echo 生成 Win32 Debug 配置... cd build_win32_debug cmake %SPDLOG_DIR% -G %GENERATOR% -A Win32 -DCMAKE_BUILD_TYPE=Debug cd .. echo 生成 Win32 Release 配置... cd build_win32_release cmake %SPDLOG_DIR% -G %GENERATOR% -A Win32 -DCMAKE_BUILD_TYPE=Release cd .. echo 所有配置生成完成! pause

方法2:手动命令编译

# 1. x64 Debugmkdirbuild_x64_debug&&cdbuild_x64_debug cmake..-G"Visual Studio 17 2022"-A x64 -DCMAKE_BUILD_TYPE=Debug cmake --build.--config Debugcd..# 2. x64 Releasemkdirbuild_x64_release&&cdbuild_x64_release cmake..-G"Visual Studio 17 2022"-A x64 -DCMAKE_BUILD_TYPE=Release cmake --build.--config Releasecd..# 3. Win32 Debugmkdirbuild_win32_debug&&cdbuild_win32_debug cmake..-G"Visual Studio 17 2022"-A Win32 -DCMAKE_BUILD_TYPE=Debug cmake --build.--config Debugcd..# 4. Win32 Releasemkdirbuild_win32_release&&cdbuild_win32_release cmake..-G"Visual Studio 17 2022"-A Win32 -DCMAKE_BUILD_TYPE=Release cmake --build.--config Releasecd..

三、完整的编译脚本

build_all.bat:

@echo off setlocal enabledelayedexpansion echo ============================================ echo SPDLOG 多平台编译脚本 echo ============================================ echo. set SRC_DIR=%~dp0 if "%SRC_DIR%"=="" set SRC_DIR=%cd% set BUILD_TYPES=Debug Release set ARCH_TYPES=x64 Win32 set VS_GENERATOR="Visual Studio 17 2022" REM 编译配置 set CMAKE_OPTIONS=-DSPDLOG_BUILD_SHARED=ON ^ -DSPDLOG_BUILD_EXAMPLE=OFF ^ -DSPDLOG_BUILD_TESTS=OFF ^ -DSPDLOG_INSTALL=ON REM 遍历所有配置 for %%a in (%ARCH_TYPES%) do ( for %%b in (%BUILD_TYPES%) do ( set BUILD_DIR=build_%%a_%%b echo. echo ============================================ echo 编译配置: %%a - %%b echo ============================================ REM 创建构建目录 if exist !BUILD_DIR! ( echo 清理目录: !BUILD_DIR! rmdir /s /q !BUILD_DIR! ) mkdir !BUILD_DIR! cd !BUILD_DIR! REM 生成 CMake 配置 echo 生成 CMake 配置... cmake %SRC_DIR% -G %VS_GENERATOR% -A %%a %CMAKE_OPTIONS% if errorlevel 1 ( echo CMake 配置失败! cd .. exit /b 1 ) REM 编译项目 echo 编译 %%b 版本... cmake --build . --config %%b -- /m if errorlevel 1 ( echo 编译失败! cd .. exit /b 1 ) REM 安装(可选) echo 安装库文件... cmake --install . --config %%b --prefix "install_%%a_%%b" cd .. echo 完成: !BUILD_DIR! ) ) echo. echo ============================================ echo 所有配置编译完成! echo ============================================ echo. echo 输出目录结构: echo ├── build_x64_Debug/ echo │ ├── spdlog.dll (Debug x64) echo │ ├── spdlog.lib echo │ └── install_x64_Debug/ echo ├── build_x64_Release/ echo │ ├── spdlog.dll (Release x64) echo │ ├── spdlog.lib echo │ └── install_x64_Release/ echo ├── build_Win32_Debug/ echo │ ├── spdlog.dll (Debug Win32) echo │ ├── spdlog.lib echo │ └── install_Win32_Debug/ echo └── build_Win32_Release/ echo ├── spdlog.dll (Release Win32) echo ├── spdlog.lib echo └── install_Win32_Release/ echo. pause

四、单独编译各版本命令

编译 x64 Debug

mkdir build_x64_debug cd build_x64_debug cmake .. -G "Visual Studio 17 2022" -A x64 ^ -DCMAKE_BUILD_TYPE=Debug ^ -DSPDLOG_BUILD_SHARED=ON cmake --build . --config Debug

编译 x64 Release

mkdir build_x64_release cd build_x64_release cmake .. -G "Visual Studio 17 2022" -A x64 ^ -DCMAKE_BUILD_TYPE=Release ^ -DSPDLOG_BUILD_SHARED=ON cmake --build . --config Release

编译 Win32 Debug

mkdir build_win32_debug cd build_win32_debug cmake .. -G "Visual Studio 17 2022" -A Win32 ^ -DCMAKE_BUILD_TYPE=Debug ^ -DSPDLOG_BUILD_SHARED=ON cmake --build . --config Debug

编译 Win32 Release

mkdir build_win32_release cd build_win32_release cmake .. -G "Visual Studio 17 2022" -A Win32 ^ -DCMAKE_BUILD_TYPE=Release ^ -DSPDLOG_BUILD_SHARED=ON cmake --build . --config Release

五、打包为可分发库

package_libs.bat:

@echo off setlocal set VERSION=1.12.0 set PACKAGE_DIR=spdlog-%VERSION%-windows echo 创建打包目录... mkdir %PACKAGE_DIR% mkdir %PACKAGE_DIR%\include mkdir %PACKAGEDIR%\lib mkdir %PACKAGE_DIR%\bin REM 复制头文件 xcopy /E /I include %PACKAGE_DIR%\include\ echo. echo 复制库文件... echo ========================= REM x64 Debug mkdir %PACKAGE_DIR%\lib\x64\debug copy build_x64_debug\Debug\*.lib %PACKAGE_DIR%\lib\x64\debug\ 2>nul mkdir %PACKAGE_DIR%\bin\x64\debug copy build_x64_debug\Debug\*.dll %PACKAGE_DIR%\bin\x64\debug\ 2>nul REM x64 Release mkdir %PACKAGE_DIR%\lib\x64\release copy build_x64_release\Release\*.lib %PACKAGE_DIR%\lib\x64\release\ 2>nul mkdir %PACKAGE_DIR%\bin\x64\release copy build_x64_release\Release\*.dll %PACKAGE_DIR%\bin\x64\release\ 2>nul REM Win32 Debug mkdir %PACKAGE_DIR%\lib\win32\debug copy build_win32_debug\Debug\*.lib %PACKAGE_DIR%\lib\win32\debug\ 2>nul mkdir %PACKAGE_DIR%\bin\win32\debug copy build_win32_debug\Debug\*.dll %PACKAGE_DIR%\bin\win32\debug\ 2>nul REM Win32 Release mkdir %PACKAGE_DIR%\lib\win32\release copy build_win32_release\Release\*.lib %PACKAGE_DIR%\lib\win32\release\ 2>nul mkdir %PACKAGE_DIR%\bin\win32\release copy build_win32_release\Release\*.dll %PACKAGE_DIR%\bin\win32\release\ 2>nul REM 创建配置文件 echo Creating CMake config files... ( echo # SPDLOG Config echo set(SPDLOG_VERSION %VERSION%) echo set(SPDLOG_INCLUDE_DIRS \${CMAKE_CURRENT_LIST_DIR}/../include) echo. echo # Import targets echo if(NOT TARGET spdlog::spdlog) echo add_library(spdlog::spdlog SHARED IMPORTED) echo. echo # x64 Debug echo set_target_properties(spdlog::spdlog PROPERTIES echo IMPORTED_CONFIGURATIONS Debug echo IMPORTED_IMPLIB_DEBUG \${CMAKE_CURRENT_LIST_DIR}/lib/x64/debug/spdlogd.lib echo IMPORTED_LOCATION_DEBUG \${CMAKE_CURRENT_LIST_DIR}/bin/x64/debug/spdlogd.dll echo ) echo. echo # x64 Release echo set_target_properties(spdlog::spdlog PROPERTIES echo IMPORTED_CONFIGURATIONS Release echo IMPORTED_IMPLIB_RELEASE \${CMAKE_CURRENT_LIST_DIR}/lib/x64/release/spdlog.lib echo IMPORTED_LOCATION_RELEASE \${CMAKE_CURRENT_LIST_DIR}/bin/x64/release/spdlog.dll echo ) echo endif() ) > %PACKAGE_DIR%\spdlog-config.cmake echo. echo 打包完成: %PACKAGE_DIR% echo 包含: echo - x64 Debug/Release (DLL + LIB) echo - Win32 Debug/Release (DLL + LIB) echo - 头文件 echo - CMake 配置文件 REM 压缩打包 powershell Compress-Archive -Path %PACKAGE_DIR% -DestinationPath %PACKAGE_DIR%.zip echo. echo 已创建压缩包: %PACKAGE_DIR%.zip pause

六、使用注意事项

1. 编译器版本对应关系

Visual Studio 版本 CMake 生成器名称 VS 2022 "Visual Studio 17 2022" VS 2019 "Visual Studio 16 2019" VS 2017 "Visual Studio 15 2017"

2. 文件命名规则

Debug 版本: spdlogd.lib / spdlogd.dll Release 版本: spdlog.lib / spdlog.dll

3. 在项目中使用

CMakeLists.txt:

# 根据配置选择库文件 if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(ARCH_DIR "x64") else() set(ARCH_DIR "win32") endif() if(CMAKE_BUILD_TYPE STREQUAL "Debug") set(CONFIG_DIR "debug") set(LIB_NAME "spdlogd") else() set(CONFIG_DIR "release") set(LIB_NAME "spdlog") endif() # 设置库路径 set(SPDLOG_LIB_DIR "${CMAKE_SOURCE_DIR}/libs/spdlog/lib/${ARCH_DIR}/${CONFIG_DIR}") set(SPDLOG_DLL_DIR "${CMAKE_SOURCE_DIR}/libs/spdlog/bin/${ARCH_DIR}/${CONFIG_DIR}") # 添加库 add_library(spdlog SHARED IMPORTED) set_target_properties(spdlog PROPERTIES IMPORTED_IMPLIB "${SPDLOG_LIB_DIR}/${LIB_NAME}.lib" IMPORTED_LOCATION "${SPDLOG_DLL_DIR}/${LIB_NAME}.dll" ) # 包含头文件 target_include_directories(your_target PRIVATE "${CMAKE_SOURCE_DIR}/libs/spdlog/include") target_link_libraries(your_target PRIVATE spdlog)

这样你就可以得到完整的 x64/Win32 的 Debug/Release 版本 spdlog 库了!

使用例子

完整的 spdlog 使用示例

这里我提供一个完整的 C++ 项目,包含多个 spdlog 使用场景。

项目结构

spdlog_example/ ├── CMakeLists.txt ├── main.cpp ├── logger_config.h └── advanced_logging.cpp

1. CMakeLists.txt

cmake_minimum_required(VERSION 3.10) project(SpdlogExample CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 选项:使用静态库还是动态库 option(USE_STATIC_SPDLOG "Use static spdlog library" OFF) # 查找或下载 spdlog find_package(spdlog QUIET) if(NOT spdlog_FOUND) message(STATUS "spdlog not found, downloading...") # 方法1:使用 FetchContent include(FetchContent) FetchContent_Declare( spdlog GIT_REPOSITORY https://github.com/gabime/spdlog.git GIT_TAG v1.12.0 ) FetchContent_MakeAvailable(spdlog) # 或者方法2:下载源码 # file(DOWNLOAD https://github.com/gabime/spdlog/archive/refs/tags/v1.12.0.zip # ${CMAKE_BINARY_DIR}/spdlog.zip) # execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf spdlog.zip) # add_subdirectory(${CMAKE_BINARY_DIR}/spdlog-1.12.0) endif() # 设置编译模式 if(MSVC) add_compile_options(/W4 /EHsc) if(USE_STATIC_SPDLOG) add_definitions(-DSPDLOG_COMPILED_LIB) endif() else() add_compile_options(-Wall -Wextra -pedantic) endif() # 添加可执行文件 add_executable(spdlog_example main.cpp logger_config.h advanced_logging.cpp ) # 链接 spdlog target_link_libraries(spdlog_example PRIVATE spdlog::spdlog) # 添加测试(可选) enable_testing() add_test(NAME SpdlogExample COMMAND spdlog_example) # 安装规则(可选) install(TARGETS spdlog_example RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib )

2. logger_config.h - 日志配置类

/** * @file logger_config.h * @brief spdlog 日志配置类 */#ifndefLOGGER_CONFIG_H#defineLOGGER_CONFIG_H#include<spdlog/spdlog.h>#include<spdlog/sinks/basic_file_sink.h>#include<spdlog/sinks/rotating_file_sink.h>#include<spdlog/sinks/daily_file_sink.h>#include<spdlog/sinks/stdout_color_sinks.h>#include<spdlog/sinks/windows_eventlog_sink.h>#include<spdlog/async.h>#include<memory>#include<string>#include<vector>#ifdef_WIN32#include<windows.h>#endif/** * @class LoggerManager * @brief 日志管理器,单例模式 */classLoggerManager{public:// 日志级别枚举enumclassLogLevel{TRACE=spdlog::level::trace,DEBUG=spdlog::level::debug,INFO=spdlog::level::info,WARN=spdlog::level::warn,ERROR=spdlog::level::err,CRITICAL=spdlog::level::critical,OFF=spdlog::level::off};// 日志类型enumclassLoggerType{CONSOLE,FILE,ROTATING_FILE,DAILY_FILE,CONSOLE_AND_FILE,ASYNC,EVENT_LOG// Windows only};/** * @brief 获取单例实例 */staticLoggerManager&instance(){staticLoggerManager manager;returnmanager;}/** * @brief 初始化日志系统 * @param logger_name 日志器名称 * @param type 日志类型 * @param level 日志级别 * @param file_path 文件路径(文件日志需要) * @param max_size 最大文件大小(旋转文件需要,单位MB) * @param max_files 最大文件数(旋转文件需要) */voidinitialize(conststd::string&logger_name="default",LoggerType type=LoggerType::CONSOLE_AND_FILE,LogLevel level=LogLevel::INFO,conststd::string&file_path="logs/app.log",size_t max_size=10,// 10MBsize_t max_files=5);/** * @brief 获取日志器 */std::shared_ptr<spdlog::logger>getLogger()const{returnlogger_;}/** * @brief 设置日志级别 */voidsetLevel(LogLevel level);/** * @brief 设置日志模式(同步/异步) */voidsetAsyncMode(boolasync,size_t queue_size=8192,size_t thread_count=1);/** * @brief 设置日志格式 */voidsetPattern(conststd::string&pattern);/** * @brief 立即刷新日志 */voidflush();/** * @brief 注册自定义日志器 */voidregisterCustomLogger(conststd::shared_ptr<spdlog::logger>&custom_logger);// 禁用拷贝和移动LoggerManager(constLoggerManager&)=delete;LoggerManager&operator=(constLoggerManager&)=delete;private:LoggerManager()=default;~LoggerManager();std::shared_ptr<spdlog::logger>logger_;std::vector<spdlog::sink_ptr>sinks_;boolasync_mode_=false;};// 便捷宏定义#defineLOG_TRACE(...)SPDLOG_LOGGER_TRACE(LoggerManager::instance().getLogger(),__VA_ARGS__)#defineLOG_DEBUG(...)SPDLOG_LOGGER_DEBUG(LoggerManager::instance().getLogger(),__VA_ARGS__)#defineLOG_INFO(...)SPDLOG_LOGGER_INFO(LoggerManager::instance().getLogger(),__VA_ARGS__)#defineLOG_WARN(...)SPDLOG_LOGGER_WARN(LoggerManager::instance().getLogger(),__VA_ARGS__)#defineLOG_ERROR(...)SPDLOG_LOGGER_ERROR(LoggerManager::instance().getLogger(),__VA_ARGS__)#defineLOG_CRITICAL(...)SPDLOG_LOGGER_CRITICAL(LoggerManager::instance().getLogger(),__VA_ARGS__)// 带位置的日志#defineLOG_INFO_LOC(...)SPDLOG_LOGGER_INFO(LoggerManager::instance().getLogger(),"{}:{} - {}",__FILE__,__LINE__,fmt::format(__VA_ARGS__))#endif// LOGGER_CONFIG_H

3. logger_config.cpp

/** * @file logger_config.cpp * @brief 日志配置实现 */#include"logger_config.h"#include<filesystem>namespacefs=std::filesystem;LoggerManager::~LoggerManager(){if(logger_){logger_->flush();spdlog::drop(logger_->name());}spdlog::shutdown();}voidLoggerManager::initialize(conststd::string&logger_name,LoggerType type,LogLevel level,conststd::string&file_path,size_t max_size,size_t max_files){// 清理现有日志器if(logger_){spdlog::drop(logger_->name());}sinks_.clear();// 创建 sinkswitch(type){caseLoggerType::CONSOLE:{autoconsole_sink=std::make_shared<spdlog::sinks::stdout_color_sink_mt>();sinks_.push_back(console_sink);break;}caseLoggerType::FILE:{// 确保日志目录存在fs::pathpath(file_path);fs::create_directories(path.parent_path());autofile_sink=std::make_shared<spdlog::sinks::basic_file_sink_mt>(file_path,true);sinks_.push_back(file_sink);break;}caseLoggerType::ROTATING_FILE:{fs::pathpath(file_path);fs::create_directories(path.parent_path());autorotating_sink=std::make_shared<spdlog::sinks::rotating_file_sink_mt>(file_path,max_size*1024*1024,max_files);sinks_.push_back(rotating_sink);break;}caseLoggerType::DAILY_FILE:{fs::pathpath(file_path);fs::create_directories(path.parent_path());autodaily_sink=std::make_shared<spdlog::sinks::daily_file_sink_mt>(file_path,0,0);// 每天午夜创建新文件sinks_.push_back(daily_sink);break;}caseLoggerType::CONSOLE_AND_FILE:{autoconsole_sink=std::make_shared<spdlog::sinks::stdout_color_sink_mt>();sinks_.push_back(console_sink);fs::pathpath(file_path);fs::create_directories(path.parent_path());autofile_sink=std::make_shared<spdlog::sinks::basic_file_sink_mt>(file_path,true);sinks_.push_back(file_sink);break;}caseLoggerType::ASYNC:{setAsyncMode(true);autoconsole_sink=std::make_shared<spdlog::sinks::stdout_color_sink_mt>();sinks_.push_back(console_sink);break;}#ifdef_WIN32caseLoggerType::EVENT_LOG:{autoeventlog_sink=std::make_shared<spdlog::sinks::win_eventlog_sink_mt>(logger_name);sinks_.push_back(eventlog_sink);break;}#endifdefault:throwstd::runtime_error("Unsupported logger type");}// 创建日志器if(async_mode_){logger_=spdlog::create_async<spdlog::sinks::stdout_color_sink_mt>(logger_name);}else{logger_=std::make_shared<spdlog::logger>(logger_name,begin(sinks_),end(sinks_));}// 设置日志级别setLevel(level);// 设置日志格式logger_->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [%n] [thread %t] %v");// 设置刷新级别logger_->flush_on(spdlog::level::warn);// 注册日志器spdlog::register_logger(logger_);spdlog::info("Logger initialized: {}",logger_name);}voidLoggerManager::setLevel(LogLevel level){if(logger_){logger_->set_level(static_cast<spdlog::level::level_enum>(level));}}voidLoggerManager::setAsyncMode(boolasync,size_t queue_size,size_t thread_count){if(async&&!async_mode_){spdlog::init_thread_pool(queue_size,thread_count);async_mode_=true;}async_mode_=async;}voidLoggerManager::setPattern(conststd::string&pattern){if(logger_){logger_->set_pattern(pattern);}}voidLoggerManager::flush(){if(logger_){logger_->flush();}}voidLoggerManager::registerCustomLogger(conststd::shared_ptr<spdlog::logger>&custom_logger){if(custom_logger){spdlog::register_logger(custom_logger);}}

4. main.cpp - 主程序示例

/** * @file main.cpp * @brief spdlog 使用示例 */#include"logger_config.h"#include<spdlog/fmt/ostr.h>// 支持自定义类型格式化#include<spdlog/fmt/bundled/format.h>#include<iostream>#include<thread>#include<vector>#include<chrono>#include<memory>#include<random>// 自定义类型示例structUser{std::string name;intage;std::string email;// 支持 spdlog 格式化输出friendstd::ostream&operator<<(std::ostream&os,constUser&user){returnos<<fmt::format("User{{name={}, age={}, email={}}}",user.name,user.age,user.email);}};// 演示基本日志功能voiddemo_basic_logging(){std::cout<<"=== 基础日志演示 ===\n";LOG_INFO("应用程序启动");LOG_DEBUG("调试信息:{}","这是一条调试消息");LOG_INFO("欢迎使用 spdlog,版本:{}",SPDLOG_VERSION);LOG_WARN("警告:内存使用率达到 {}%",85.5);LOG_ERROR("错误:文件 {} 不存在","config.json");// 带参数的格式化LOG_INFO("用户 {} 在 {} 登录","张三","2024-01-15 10:30:00");// 条件日志intretry_count=3;SPDLOG_LOGGER_INFO(LoggerManager::instance().getLogger(),"重试次数: {}, 状态: {}",retry_count,retry_count>0?"继续":"停止");}// 演示多线程日志voiddemo_multithread_logging(){std::cout<<"\n=== 多线程日志演示 ===\n";std::vector<std::thread>threads;constintthread_count=5;autoworker=[](intid){for(inti=0;i<3;++i){LOG_INFO("线程 {} - 任务 {}",id,i);std::this_thread::sleep_for(std::chrono::milliseconds(100));}};for(inti=0;i<thread_count;++i){threads.emplace_back(worker,i+1);}for(auto&t:threads){t.join();}LOG_INFO("所有线程执行完成");}// 演示性能日志voiddemo_performance_logging(){std::cout<<"\n=== 性能日志演示 ===\n";autostart=std::chrono::high_resolution_clock::now();// 模拟一些工作std::random_device rd;std::mt19937gen(rd());std::uniform_int_distribution<>dis(1,100);intsum=0;constintiterations=1000000;for(inti=0;i<iterations;++i){sum+=dis(gen);}autoend=std::chrono::high_resolution_clock::now();autoduration=std::chrono::duration_cast<std::chrono::milliseconds>(end-start);// 使用性能日志级别LOG_INFO("计算完成,迭代次数: {}, 总和: {}, 耗时: {} ms",iterations,sum,duration.count());// 日志级别控制LoggerManager::instance().setLevel(LoggerManager::LogLevel::DEBUG);LOG_DEBUG("详细性能数据: 平均每次迭代耗时: {:.6f} ms",duration.count()/static_cast<double>(iterations));}// 演示自定义类型日志voiddemo_custom_type_logging(){std::cout<<"\n=== 自定义类型日志演示 ===\n";User user{"张三",25,"zhangsan@example.com"};LOG_INFO("用户信息: {}",user);std::vector<User>users={{"李四",30,"lisi@example.com"},{"王五",28,"wangwu@example.com"},{"赵六",35,"zhaoliu@example.com"}};LOG_INFO("用户列表:");for(constauto&u:users){LOG_INFO(" - {}",u);}}// 演示异常日志voiddemo_exception_logging(){std::cout<<"\n=== 异常日志演示 ===\n";try{throwstd::runtime_error("模拟业务异常");}catch(conststd::exception&e){LOG_ERROR("捕获异常: {}, 位置: {}:{}",e.what(),__FILE__,__LINE__);// 记录堆栈信息(需要其他库支持,这里只是示例)LOG_ERROR("异常堆栈:");LOG_ERROR(" - main()");LOG_ERROR(" - demo_exception_logging()");LOG_ERROR(" - std::runtime_error::runtime_error()");}}// 演示不同日志级别voiddemo_log_levels(){std::cout<<"\n=== 日志级别演示 ===\n";auto&logger=LoggerManager::instance();// 显示所有级别的日志logger.setLevel(LoggerManager::LogLevel::TRACE);LOG_TRACE("这是一条 TRACE 级别的日志");LOG_DEBUG("这是一条 DEBUG 级别的日志");LOG_INFO("这是一条 INFO 级别的日志");LOG_WARN("这是一条 WARN 级别的日志");LOG_ERROR("这是一条 ERROR 级别的日志");LOG_CRITICAL("这是一条 CRITICAL 级别的日志");// 设置为只显示 ERROR 及以上logger.setLevel(LoggerManager::LogLevel::ERROR);LOG_INFO("这条 INFO 日志不会被显示");LOG_ERROR("这条 ERROR 日志会被显示");}// 演示文件日志voiddemo_file_logging(){std::cout<<"\n=== 文件日志演示 ===\n";auto&logger=LoggerManager::instance();// 重新初始化为文件日志logger.initialize("file_logger",LoggerManager::LoggerType::FILE,LoggerManager::LogLevel::INFO,"logs/file_demo.log");LOG_INFO("这条日志会写入文件");LOG_WARN("警告信息也会写入文件");LOG_ERROR("错误信息同样写入文件");std::cout<<"日志已写入 logs/file_demo.log 文件\n";}// 演示异步日志voiddemo_async_logging(){std::cout<<"\n=== 异步日志演示 ===\n";auto&logger=LoggerManager::instance();logger.setAsyncMode(true,8192,2);constintmessage_count=1000;autostart=std::chrono::high_resolution_clock::now();std::vector<std::thread>threads;constintthread_count=4;autoworker=[&logger](intid,intcount){for(inti=0;i<count;++i){SPDLOG_LOGGER_INFO(logger.getLogger(),"异步日志 - 线程 {} - 消息 {}",id,i);}};intmessages_per_thread=message_count/thread_count;for(inti=0;i<thread_count;++i){threads.emplace_back(worker,i+1,messages_per_thread);}for(auto&t:threads){t.join();}autoend=std::chrono::high_resolution_clock::now();autoduration=std::chrono::duration_cast<std::chrono::milliseconds>(end-start);LOG_INFO("异步日志完成,总共 {} 条消息,耗时 {} ms",message_count,duration.count());// 等待异步队列清空logger.flush();}// 演示日志配置voiddemo_logger_configuration(){std::cout<<"\n=== 日志配置演示 ===\n";auto&logger=LoggerManager::instance();// 1. 自定义日志格式logger.setPattern("[%Y-%m-%d %H:%M:%S] [%l] [%n] %v");LOG_INFO("自定义格式日志");// 2. 恢复默认格式logger.setPattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [%n] [thread %t] %v");LOG_INFO("恢复默认格式");// 3. 设置不同的日志级别logger.setLevel(LoggerManager::LogLevel::WARN);LOG_INFO("这条 INFO 日志不会显示");LOG_WARN("这条 WARN 日志会显示");// 4. 刷新日志logger.flush();LOG_INFO("日志已刷新到磁盘");}intmain(){try{// 初始化日志系统LoggerManager::instance().initialize("demo_logger",LoggerManager::LoggerType::CONSOLE_AND_FILE,LoggerManager::LogLevel::INFO,"logs/demo.log");// 设置全局异常处理器spdlog::set_error_handler([](conststd::string&msg){std::cerr<<"spdlog 错误: "<<msg<<std::endl;});// 运行各种演示demo_basic_logging();demo_multithread_logging();demo_performance_logging();demo_custom_type_logging();demo_exception_logging();demo_log_levels();demo_file_logging();demo_async_logging();demo_logger_configuration();// 程序结束日志LOG_INFO("程序正常退出");}catch(conststd::exception&e){std::cerr<<"程序异常: "<<e.what()<<std::endl;return1;}return0;}

5. advanced_logging.cpp - 高级功能演示

/** * @file advanced_logging.cpp * @brief spdlog 高级功能演示 */#include"logger_config.h"#include<spdlog/sinks/ostream_sink.h>#include<spdlog/sinks/udp_sink.h>#include<spdlog/sinks/tcp_sink.h>#include<spdlog/sinks/syslog_sink.h>#include<spdlog/sinks/android_sink.h>#include<spdlog/fmt/bin_to_hex.h>#include<sstream>#include<fstream>#include<iomanip>// 演示二进制数据日志voiddemo_binary_logging(){std::cout<<"\n=== 二进制数据日志演示 ===\n";unsignedcharbinary_data[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};LOG_INFO("二进制数据: {}",spdlog::to_hex(binary_data,sizeof(binary_data)));LOG_INFO("带 ASCII 显示: {}",spdlog::to_hex(binary_data,sizeof(binary_data),true));// 格式化显示std::string hex_dump=spdlog::to_hex(binary_data,sizeof(binary_data),8);LOG_INFO("格式化十六进制:\n{}",hex_dump);}// 演示条件编译日志voiddemo_conditional_logging(){std::cout<<"\n=== 条件编译日志演示 ===\n";#ifdef_DEBUGLOG_DEBUG("这是调试版本");#elseLOG_INFO("这是发布版本");#endif// SPDLOG_LOGGER_CALL 宏interror_code=404;SPDLOG_LOGGER_CALL(LoggerManager::instance().getLogger(),spdlog::level::err,"错误代码: {}",error_code);}// 演示流式日志(不推荐,性能较低)voiddemo_stream_logging(){std::cout<<"\n=== 流式日志演示 ===\n";// 注意:流式日志性能较低,建议使用格式化字符串autologger=LoggerManager::instance().getLogger();SPDLOG_LOGGER_INFO(logger,"流式日志: "<<"第一部分 "<<123<<" 第二部分");}// 演示自定义 sinkvoiddemo_custom_sink(){std::cout<<"\n=== 自定义 Sink 演示 ===\n";// 创建 stringstream sinkautooss_sink=std::make_shared<spdlog::sinks::ostream_sink_mt>(std::cout);autocustom_logger=std::make_shared<spdlog::logger>("custom",oss_sink);custom_logger->set_pattern("[custom] %v");custom_logger->info("这是通过自定义 sink 输出的日志");// 注册到管理器LoggerManager::instance().registerCustomLogger(custom_logger);}// 演示速率限制日志voiddemo_rate_limited_logging(){std::cout<<"\n=== 速率限制日志演示 ===\n";// spdlog 本身没有内置速率限制,但可以通过条件控制staticintlog_count=0;staticautolast_log_time=std::chrono::steady_clock::now();autonow=std::chrono::steady_clock::now();autoelapsed=std::chrono::duration_cast<std::chrono::seconds>(now-last_log_time);if(elapsed.count()>=1){// 每秒最多一条LOG_INFO("速率限制日志 - 计数: {}",++log_count);last_log_time=now;}}// 演示结构化日志(JSON 格式)voiddemo_structured_logging(){std::cout<<"\n=== 结构化日志演示 ===\n";// 设置为 JSON 格式LoggerManager::instance().setPattern("{\"timestamp\":\"%Y-%m-%dT%H:%M:%S.%eZ\",""\"level\":\"%l\",""\"thread\":%t,""\"message\":\"%v\"}");LOG_INFO("用户登录成功");LOG_WARN("内存使用率偏高");// 恢复默认格式LoggerManager::instance().setPattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] %v");}// 演示日志轮转voiddemo_log_rotation(){std::cout<<"\n=== 日志轮转演示 ===\n";auto&logger=LoggerManager::instance();// 重新初始化为旋转文件日志logger.initialize("rotation_logger",LoggerManager::LoggerType::ROTATING_FILE,LoggerManager::LogLevel::INFO,"logs/rotation.log",1,// 1MB3);// 保留3个文件// 生成大量日志以触发轮转for(inti=0;i<1000;++i){LOG_INFO("这是第 {} 条日志消息,用于测试日志轮转功能",i);}std::cout<<"已生成测试日志,检查 logs/ 目录下的 rotation.log 文件\n";}// 演示系统日志(Linux/Unix)voiddemo_syslog_logging(){std::cout<<"\n=== 系统日志演示 ===\n";#ifndef_WIN32// Linux/Unix 系统日志try{autosyslog_sink=std::make_shared<spdlog::sinks::syslog_sink_mt>("spdlog_demo");autosyslog_logger=std::make_shared<spdlog::logger>("syslog",syslog_sink);syslog_logger->info("这是一条系统日志消息");LoggerManager::instance().registerCustomLogger(syslog_logger);}catch(constspdlog::spdlog_ex&ex){LOG_WARN("系统日志不可用: {}",ex.what());}#elseLOG_INFO("Windows 系统不支持 Unix 系统日志");#endif}// 演示网络日志(UDP/TCP)voiddemo_network_logging(){std::cout<<"\n=== 网络日志演示 ===\n";LOG_INFO("网络日志功能需要额外的网络配置");LOG_INFO("可以使用 udp_sink 或 tcp_sink 发送日志到远程服务器");// 示例代码(需要服务器支持)/* try { // UDP 日志 auto udp_sink = std::make_shared<spdlog::sinks::udp_sink_mt>("127.0.0.1", 9999); auto udp_logger = std::make_shared<spdlog::logger>("udp", udp_sink); udp_logger->info("UDP 日志消息"); // TCP 日志 auto tcp_sink = std::make_shared<spdlog::sinks::tcp_sink_mt>("127.0.0.1", 9998); auto tcp_logger = std::make_shared<spdlog::logger>("tcp", tcp_sink); tcp_logger->info("TCP 日志消息"); } catch (const std::exception& e) { LOG_ERROR("网络日志错误: {}", e.what()); } */}// 演示日志分析voiddemo_log_analysis(){std::cout<<"\n=== 日志分析演示 ===\n";// 读取日志文件进行分析std::ifstreamlog_file("logs/demo.log");if(log_file.is_open()){std::string line;intinfo_count=0,error_count=0,warn_count=0;while(std::getline(log_file,line)){if(line.find("[info]")!=std::string::npos)info_count++;if(line.find("[error]")!=std::string::npos)error_count++;if(line.find("[warn]")!=std::string::npos)warn_count++;}LOG_INFO("日志分析结果:");LOG_INFO(" INFO 消息: {} 条",info_count);LOG_INFO(" WARN 消息: {} 条",warn_count);LOG_INFO(" ERROR 消息: {} 条",error_count);log_file.close();}else{LOG_WARN("无法打开日志文件进行分析");}}

6. 编译和运行

Windows (MSVC):

# 创建构建目录mkdirbuild&&cdbuild# 配置 CMake(根据你的 VS 版本调整)cmake..-G"Visual Studio 17 2022"-A x64# 编译cmake --build.--config Release# 运行.\Release\spdlog_example.exe

Linux/Mac:

mkdirbuild&&cdbuild cmake..-DCMAKE_BUILD_TYPE=Releasemake-j4 ./spdlog_example

7. 示例输出

程序运行后会:

  1. 在控制台输出彩色日志
  2. logs/目录下生成日志文件
  3. 演示各种日志功能
=== 基础日志演示 === [2024-01-15 10:30:00.123] [INFO] [demo_logger] 应用程序启动 [2024-01-15 10:30:00.124] [INFO] [demo_logger] 欢迎使用 spdlog,版本:1.12.0 [2024-01-15 10:30:00.125] [WARN] [demo_logger] 警告:内存使用率达到 85.5% === 多线程日志演示 === [2024-01-15 10:30:00.126] [INFO] [demo_logger] 线程 1 - 任务 0 [2024-01-15 10:30:00.126] [INFO] [demo_logger] 线程 2 - 任务 0 ...

8. 主要特点

这个示例展示了:

  • ✅ 多线程安全日志
  • ✅ 彩色控制台输出
  • ✅ 文件日志(普通、轮转、每日)
  • ✅ 异步日志(高性能)
  • ✅ 自定义日志格式
  • ✅ 结构化日志(JSON)
  • ✅ 二进制数据日志
  • ✅ 异常日志记录
  • ✅ 性能监控日志
  • ✅ 条件编译日志
  • ✅ 自定义类型支持
  • ✅ 日志级别控制
  • ✅ 日志刷新策略

你可以根据需要修改和扩展这个示例来满足具体的项目需求。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/22 20:41:13

minio分片上传

minio分片上传前言分片上传的技术选择实现分片上传第一步自定义客户端初始化分片上传获取一个上传分片的url共前端使用确认每一个分片的上传合并分片文件前言 为什么要选择将一个大文件拆分成许多小文件来上传&#xff1f; 对于许多服务器和应用框架来说&#xff0c;单次HTTP…

作者头像 李华
网站建设 2026/1/19 2:09:46

基于MATLAB实现深度学习图像分类

一、环境配置与数据准备 1.1 环境要求 MATLAB版本&#xff1a;R2021a及以上&#xff08;需安装Deep Learning Toolbox&#xff09;GPU支持&#xff1a;推荐NVIDIA CUDA兼容显卡&#xff08;通过gpuDevice验证&#xff09; 1.2 数据组织结构 dataset/ ├── train/ │ ├──…

作者头像 李华
网站建设 2026/1/18 2:46:21

9、UNIX/Linux 文件操作全解析

UNIX/Linux 文件操作全解析 1. 文件内容的初步探索 当你尝试使用 cat 命令查看文件内容时,可能会遇到权限问题,例如: $ cat myfile cat: myfile: Permission denied若已知文件存在,我们自然会想知道它的内容。虽然文件本质是字节序列,但我们更关心这些字节代表什么。…

作者头像 李华
网站建设 2026/1/18 18:27:14

企业SRC支付漏洞EDUSRC众测挖掘思路技巧操作分享

0x1 前言这篇文章也是给师傅们分享几个SRC漏洞挖掘中的技巧点&#xff0c;两个企业SRC漏洞案例&#xff0c;支付漏洞中&#xff0c;师傅们碰到都可以进行尝试验证下&#xff0c;要是挖到了&#xff0c;像众测中就是中、高危起步了。赏金的价格还不错&#xff0c;两个案例也写的…

作者头像 李华
网站建设 2026/1/22 15:44:51

webpack输出代码报错到指定文本文件

文章目录 概述代码 概述 在vscode的控制台输出的报错是有限的&#xff0c;多了就看不全了。想要看全部代码报错&#xff0c;就产生了如下方式&#xff1a; 代码 // 在package.json的scripts下&#xff0c;增加以下配置&#xff1a; start2: "set NO_COLOR1 && …

作者头像 李华
网站建设 2026/1/21 14:34:08

自然语言处理容易混淆知识点(二)BERT和BERTopic的区别

BERT和BERTopicBERT&#xff08;深度学习模型&#xff09;BERTopic&#xff08;主题建模工具包&#xff09;关系类比详细对比1. BERT&#xff1a;基础组件2. BERTopic&#xff1a;完整系统技术架构图关键区别表格实际代码对比**只用 BERT**使用 BERTopic常见混淆点澄清1. 名字为…

作者头像 李华