核心背景:桌面程序 Release 版一般关闭控制台输出,不能靠
printf/qDebug看日志;日志需要落地到文件、支持分级、滚动切割,还要兼顾性能、跨平台、易用性。 下面以 C++/Qt 桌面场景为主(你正在做Qt项目),同时覆盖通用思路。
一、先梳理项目需要哪些日志能力(选型判断清单)
先明确需求,再选框架,不要上来直接用最火的库:
基础需求
- 日志级别:Trace/Debug/Info/Warn/Error/Fatal,Release 可动态关闭低级别日志
- 文件输出:写入本地文件,而不是只打印控制台
- 日志滚动(最重要!桌面必选)
- 按大小切割:单个日志文件到一定大小新建文件
- 按时间切割:按天/小时生成日志
- 自动清理旧日志,防止日志占满磁盘(工控桌面尤其重要)
- 日志内容:时间戳、线程ID、文件/行号、模块名
进阶需求(按需勾选)
- ✅跨平台:Windows + Linux(Ubuntu),你的项目需要
- ✅性能:高频打点(如相机、传感器数据),是否支持异步日志(避免阻塞UI主线程)
- ✅是否依赖第三方库:不想引入重型依赖?还是可以接受
- ✅日志编码:Windows下中文不乱码(大坑!Qt桌面常见)
- ✅附加输出:除文件外,是否同时输出到调试器、MQTT上传日志、弹窗提示错误
- ✅崩溃捕获:程序crash时,自动打印堆栈到日志
- ✅配置能力:日志级别、保存路径、保留天数,可配置文件控制,不用重编程序
二、C++桌面常用日志框架对比(Qt项目优先看)
1. spdlog(⭐推荐首选,Qt跨平台项目)
目前C++桌面最流行,轻量、头文件可选、性能强
- 特点
- 支持同步/异步模式,异步适合高频日志,不阻塞UI
- 内置日志滚动:按大小、按时间,自动删旧文件
- 跨平台 Windows/Linux,完美适配Qt
- 头文件版本,集成简单;也有编译库版本
- 支持自定义格式,线程安全
- 适合场景:绝大多数C++/Qt桌面软件,包括工控终端(你的sdnkCarTerminal这类项目)
- 缺点:
- 没有自带崩溃堆栈捕获,需要搭配
backtrace/Breakpad - 中文路径Windows下需要注意编码(utf8路径)
- 没有自带崩溃堆栈捕获,需要搭配
Qt集成小技巧:可以封装一个全局logger,把
qDebug/qWarning重定向输出到spdlog,原有代码不用大规模改。
2. Boost.Log
- 特点:功能极其全面,过滤器、多后端、自定义属性一应俱全;跨平台
- 适合:项目本身已经依赖Boost库
- 缺点:重型库,编译复杂;二进制体积大;学习成本高。新项目不推荐只为日志引入Boost。
3. easylogging++
- 特点:轻量单头文件,上手简单,自带滚动
- 缺点:异步性能弱,高频率打印会卡顿;维护活跃度一般。适合小型工具,不适合持续高频日志(如相机采集)。
4. glog(Google Logging Library)
- 特点:稳定,Google出品;自带崩溃dump;支持按大小切割
- 缺点:没有内置按时间滚动;旧版本配置麻烦;默认行为容易产生大量小文件;Windows中文路径坑较多。 适合:需要崩溃堆栈捕获,低频日志场景。
5. Qt 原生方案:qInstallMessageHandler(不推荐大型项目)
Qt自带日志回调,可以自己写文件保存
void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { // 自行打开文件、追加日志、手动实现滚动 }✅优点:零依赖,只靠Qt,小工具快速开发 ❌缺点:自己实现日志滚动、线程安全、文件锁、旧日志清理,很容易写出bug;异步要自己封装;高频IO会卡主线程。
适合:简单小工具;不适合工控、长时间运行的桌面终端。
6. 其他备选
- log4cpp:老牌log4j风格,比较老旧,维护少,不推荐新项目
- plog:轻量,类似spdlog,体积更小,功能略少,适合资源受限设备
三、按项目类型快速选型建议
- Qt跨平台工控桌面终端(你的场景,长时间运行、有传感器/相机打点)👉spdlog(异步模式)搭配:可选Breakpad捕获崩溃堆栈;重定向qDebug到spdlog;日志按天+大小双滚动,保留最近7天日志。
- 小型桌面工具,日志量很低,不想引入额外第三方库👉 Qt
qInstallMessageHandler手写简易日志(只做基础文件输出,日志量小没问题) - 项目本身已经依赖Boost👉 Boost.Log
- 需要稳定崩溃dump,日志量不大👉 glog
四、Release版本日志最佳实践(桌面开发重点)
- 日志分级控制
- Debug版:打开 Trace/Debug
- Release:默认只开启 Info/Warn/Error/Fatal,关闭Debug日志,减少IO开销
- 高级:支持运行时动态修改日志级别(读取ini/json配置,不用重新编译)
- 日志路径Windows:不要写程序安装目录(权限问题),写到
%APPDATA%/你的程序名/logsLinux:~/.local/share/xxx/logs或者/var/log/xxx(工控机注意权限) - 日志滚动策略(推荐组合)限制单个文件最大 10~50MB,同时按天分割;最多保留N个文件,自动删除过期日志,防止磁盘占满(工控设备致命问题)
- 线程安全 + 异步打印UI线程不要直接写文件IO!异步日志把日志任务丢到后台线程,避免界面卡顿。spdlog异步logger就是解决这个。
- 敏感信息过滤日志里不要打印密码、密钥等隐私数据。
- 崩溃日志增强日志框架本身只能记录正常打印;程序异常崩溃,需要额外库(Breakpad)捕获崩溃堆栈,写入单独的crash日志。
五、简单spdlog示例(Qt C++,文件日志+按大小滚动)
#include "spdlog/spdlog.h" #include "spdlog/sinks/rotating_file_sink.h" // 初始化全局日志 void initLogger() { // 单个文件最大10MB,最多保留5个日志文件 auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>("logs/app.log", 1024*1024*10, 5); auto logger = std::make_shared<spdlog::logger>("app_log", file_sink); spdlog::set_default_logger(logger); spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e [%l] [%t] %v"); spdlog::info("app start"); }rotating_file_sink_mt:按大小滚动、多线程安全(同步)daily_file_sink_mt:按天滚动rotating_file_sink_st:单线程版本 异步版本使用spdlog::async_factory创建异步logger。
六、总结选型判断口诀
- 追求轻量、高性能、跨平台、易集成 → spdlog(绝大多数C++桌面首选)
- 已有Boost依赖 → Boost.Log
- 小工具,不想加第三方库 → Qt消息回调手写日志
- 需要崩溃dump,日志量小 → glog