如何在程序结束时将spdlog日志刷入文件?
解决方案
1. 先给日志器添加文件输出Sink
你当前的代码仅配置了控制台输出的sink,没有写入文件的逻辑,所以第一步需要给日志器添加文件输出的sink,让日志能输出到文件中。
修改Log.h
将flush_to_file改为静态方法(匹配类内静态成员的使用逻辑):
#pragma once #include "spdlog/spdlog.h" #include "spdlog/fmt/ostr.h" namespace Engine{ class Log{ public: static void init(); inline static std::shared_ptr<spdlog::logger>& GetCoreLogger() { return s_CoreLogger; } inline static std::shared_ptr<spdlog::logger>& GetClientLogger() { return s_ClientLogger;} // 修改为静态方法,适配静态成员调用逻辑 static void flush_all_logs(); private: static std::shared_ptr<spdlog::logger> s_CoreLogger; static std::shared_ptr<spdlog::logger> s_ClientLogger; }; } //Client log macros #define VI_TRACE(...) ::Engine::Log::GetClientLogger()->trace(__VA_ARGS__) #define VI_INFO(...) ::Engine::Log::GetClientLogger()->info(__VA_ARGS__) #define VI_WARN(...) ::Engine::Log::GetClientLogger()->warn(__VA_ARGS__) #define VI_ERROR(...) ::Engine::Log::GetClientLogger()->error(__VA_ARGS__)
修改Log.cpp
添加文件sink头文件,配置多sink日志器,并实现flush方法:
#include "spdlog/sinks/stdout_color_sinks.h" // 引入文件sink头文件(基础文件输出) #include "spdlog/sinks/basic_file_sink.h" namespace Engine { std::shared_ptr<spdlog::logger> Log::s_CoreLogger; std::shared_ptr<spdlog::logger> Log::s_ClientLogger; void Log::init() { spdlog::set_pattern("%^[%T] %n: %v%$"); // 创建控制台sink和文件sink auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>(); // 基础文件sink:写入指定文件,第二个参数true表示追加模式 auto core_file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("engine_core.log", true); // 组合多sink,日志同时输出到控制台和文件 std::vector<spdlog::sink_ptr> core_sinks{console_sink, core_file_sink}; s_CoreLogger = std::make_shared<spdlog::logger>("VIO", core_sinks.begin(), core_sinks.end()); s_CoreLogger->set_level(spdlog::level::trace); // 给客户端日志器配置文件sink auto client_file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("app.log", true); std::vector<spdlog::sink_ptr> client_sinks{console_sink, client_file_sink}; s_ClientLogger = std::make_shared<spdlog::logger>("APP", client_sinks.begin(), client_sinks.end()); s_ClientLogger->set_level(spdlog::level::trace); } // 实现flush逻辑:强制将缓冲区内容写入文件 void Log::flush_all_logs(){ // 刷新单个日志器的缓冲区 s_CoreLogger->flush(); s_ClientLogger->flush(); // 也可以用全局方法刷新所有已注册的日志器 // spdlog::flush_all(); } };
2. Flush相关说明
- 手动Flush:调用
logger->flush()会立即将该日志器的内存缓冲区内容写入文件;spdlog::flush_all()则会刷新所有已初始化的日志器。你可以在程序正常退出前调用Log::flush_all_logs()确保所有日志落盘。 - 自动Flush配置:spdlog支持自动刷新策略,可在
init函数中添加:
配置自动刷新可以减少手动flush的需求,提升稳定性。// 记录error级别及以上日志时自动刷新 s_CoreLogger->flush_on(spdlog::level::err); // 每3秒自动刷新一次缓冲区 s_CoreLogger->flush_every(std::chrono::seconds(3));
3. 程序结束时调用Flush
在主程序的正常退出路径(比如main函数末尾)调用:
Engine::Log::flush_all_logs();
这样能保证所有未写入的日志都被强制刷入文件。另外,spdlog的日志器在正常销毁时也会自动flush,但如果程序异常终止(如崩溃),销毁逻辑可能无法执行,因此手动调用flush是更稳妥的做法。
内容的提问来源于stack exchange,提问作者Turgut
相关产品推荐
相关产品推荐

