You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在程序结束时将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函数中添加:
    // 记录error级别及以上日志时自动刷新
    s_CoreLogger->flush_on(spdlog::level::err);
    // 每3秒自动刷新一次缓冲区
    s_CoreLogger->flush_every(std::chrono::seconds(3));
    
    配置自动刷新可以减少手动flush的需求,提升稳定性。

3. 程序结束时调用Flush

在主程序的正常退出路径(比如main函数末尾)调用:

Engine::Log::flush_all_logs();

这样能保证所有未写入的日志都被强制刷入文件。另外,spdlog的日志器在正常销毁时也会自动flush,但如果程序异常终止(如崩溃),销毁逻辑可能无法执行,因此手动调用flush是更稳妥的做法。

内容的提问来源于stack exchange,提问作者Turgut

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 12:20:26