C++ 日志库 spdlog 使用教程
Spdlog是一个快速、异步、线程安全的C++日志库,他可以方便地记录应用程序的运行状态,并提供多种输出格式。官网:https://github.com/gabime/spdlog
安装教程可以参考:https://blog.csdn.net/Harrytsz/article/details/144887297
Spdlog的优点:
- 只包含头文件
- 速度很快
- 无需依赖第三方库
- 支持跨平台
- 支持多线程—线程安全
- 可对日志文件进行循环输出
- 可每日生成日志文件
- 可支持控制台日志输出
- 可选的异步输出
- 可定义日志格式
1、日志级别
trace = SPDLOG_LEVEL_TRACE // 最低级(用来记录代码执行轨迹)
debug = SPDLOG_LEVEL_DEBUG // (用来记录debug信息)
info = SPDLOG_LEVEL_INFO // 在上面的测试例子中用过
warn = SPDLOG_LEVEL_WARN
err = SPDLOG_LEVEL_ERROR
critical = SPDLOG_LEVEL_CRITICAL
off = SPDLOG_LEVEL_OFF // 最高级
2、控制台打印日志
方式一,最简单的使用方式,将日志输出到控制台。
#include <iostream>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>void stdout_easy()
{// 根据参数,在内部创建了一个名为 "console" 的 logger,返回 logger 的智能指针。auto console = spdlog::stdout_color_mt("console");// 通过智能指针调用 logger 对象的函数。console->info("hello world");
}
int main()
{stdout_easy();return 0;
}
输出结果:

方式二,
#include <iostream>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>void stdout_example() {// create a color multi-threaded logger// spdlog::stdout_color_mt("console")函数创建一个名字为console的console logger,// 把这个 logger 注册到 spdlog 的全局注册表中,并且返回指向这个 logger 的指针(shared_ptr)auto console_stdout = spdlog::stdout_color_mt("console");// 如果我们不知道上方创建函数返回的指针,我们也可以直接通过 logger 名称来获取对应 logger // 通过 get 来获取已经创建好的 logger,获取方式通过指针名,同时使用 info 函数输出日志内容spdlog::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name)");
}int main() {stdout_example();return 0;
}
输出结果:

3、保存日志文件
下面的案例将日志记录保存到文件中,以便于长久保存。basic_logger_mt 只是 spdlog 中封装的其中一个日志记录器,还有很多其他的记录器。
#include<iostream>
#include<spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>int main() {// 创建一个名为 basic_logger 的日志记录器,并且返回指针。// mt 表示多线程,意味着多个线程中使用同一个日志记录器。// 需要注意的是在文件内添加数据是通过追加的形式进行的,并且如果没有创建文件会自动创建文件。auto basic_logger = spdlog::basic_logger_mt("basic_logger", "./logs/basic_log.txt");for (int i = 0; i < 10000; i++) {basic_logger->info("Test file logger{}", i);}return 0;
}

4、自定义日志记录器
我们根据以上的学习之后,大体了解了其中的运行机制,所以我们就可以不使用他封装的日志记录器,而是使用他内部的 logger 对象封装适合自己的日志记录器。
需要注意的是,所谓的不同的日志记录器其实就是不同的 logger 对象,那么用什么来区分不同的 logger 对象呢,就是用创建logger对象时传入的参数 sink 对象,这个sink对象标记着不同的类型,把他作为参数 logger 会根据 sink 对象类型的不同创建不同的日志记录器。
这种方式有很大的用途,比如我们可以创建一个日志记录器,但是里边有多个类型的 sink,从而可以一个 logger 能够实现多种效果。
#include<iostream>
#include<spdlog/spdlog.h>
//#include <spdlog/sinks/stdout_sinks.h>
#include <spdlog/sinks/stdout_color_sinks.h>void make_console_spdlog() {/*auto console_level = std::make_shared<spdlog::sinks::stdout_sink_mt>();*/ // 黑白日志auto console_level = std::make_shared<spdlog::sinks::stdout_color_sink_mt>(); // 彩色日志auto console = std::make_shared<spdlog::logger>("console", console_level);console->info("hello world");
}int main() {make_console_spdlog();return 0;
}
输出结果:

注意:通过手动创建的日志记录器是无法通过名字在 spdlog 中进行查找的,因为他并没有注册到 spdlog 的全局注册表。
void make_console_spdlog() {auto console_level = std::make_shared<spdlog::sinks::stdout_sink_mt>();auto console = std::make_shared<spdlog::logger>("console", console_level);// 直接使用这种方式去获取日志记录器发生错误spdlog::get("console")->info("hello world!");
}
所以在创建日志记录器完成后,要将其注册到spdlog的全局注册表中。
#include<iostream>
#include<spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>void make_console_spdlog() {auto console_level = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();auto console = std::make_shared<spdlog::logger>("console", console_level);// 将创建的日志记录器注册到全局注册表中spdlog::register_logger(console);spdlog::get("console")->info("hello world!");
}int main() {make_console_spdlog();return 0;
}
5、多记录器共享文件
#include <iostream>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>void multi_file_write()
{// 创建filesink,以便多个日志共享器共享。auto filesink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("./logs/multilogger.txt");// 创建两个日志记录器来进行测试auto onelogger = std::make_shared<spdlog::logger>("onelogger", filesink);auto twologger = std::make_shared<spdlog::logger>("twologger", filesink);// 注册进spdlog的全局注册表spdlog::register_logger(onelogger);spdlog::register_logger(twologger);for (int i = 0; i < 100; i++) {onelogger->info("onelogger write:{}", i);twologger->info("twologger write:{}", i);}
}int main() {multi_file_write();return 0;
}

6、日志分割
在我们的应用程序有很多日志需要记录时,每个日志文件就会变得非常大,这样就会影响应用程序的性能以及稳定性。所以为了解决这个问题,可以使用Spdlog的日志分割功能。
rotating log 滚动日志,当日志文件超出规定大小时,会删除当前日志文件中所有内容,重新开始写入
#include<iostream>
#include<spdlog/spdlog.h>
#include <spdlog/sinks/rotating_file_sink.h>void rotaing_file() {// 首先定义要使用分割文件的大小和数量int max_size = 1048576 * 5;int file_size = 3;// 创建 rotaing_logger_mt 日志记录器auto rotaing_file = spdlog::rotating_logger_mt("rotaing_file", "./logs/rotaingLogger.txt", max_size, file_size);for (int i = 0; i < 100000; i++) {rotaing_file->info("rotaing file:{}", i);}
}int main() {rotaing_file();return 0;
}
7、定时日志
Spdlog还可以实现定时创建文件存储日志的功能。
#include<iostream>
#include<spdlog/spdlog.h>
#include <spdlog/sinks/daily_file_sink.h>void daily_log() {// 创建daily_log日志// 参数介绍 1日志记录器名称 2文件名 3时 4分auto daily_log = spdlog::daily_logger_mt("daily_log", "./logs/daily_log.txt", 16, 18);for (int i = 0; i < 100000; i++) {daily_log->info("daily log print {}", i);}
}int main() {daily_log();return 0;
}
8、记录器包含多个 sink
#include<iostream>
#include<spdlog/spdlog.h>
#include<spdlog/sinks/stdout_color_sinks.h>
#include<spdlog/sinks/basic_file_sink.h>void multi_sink() {// 创建两个sink,一个用于控制台输出,一个用于文件输出auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("./logs/multi_sink.txt");// 设置两者输出等级console_sink->set_level(spdlog::level::info);file_sink->set_level(spdlog::level::debug);// 将两种不同的sink放到一个日志输出器中auto multi_sink = std::make_shared<spdlog::logger>("multi_sink", spdlog::sinks_init_list({ console_sink, file_sink }));multi_sink->set_level(spdlog::level::debug);// 输出不同等级日志测试multi_sink->info("hello world info");multi_sink->debug("hello world debug");
}int main() {multi_sink();return 0;
}
9、其他介绍
通过上面的学习,我们学会了 spdlog 其函数的基本使用方式,下面对 spdlog 中常用的一些函数和类进行介绍。
- level_enum:日志等级枚举,包括trace、info、debug、warn、err、critical、off、n_levels。
- sink:日志记录槽,进行底层操作(比如格式化内容,输出内容到控制台/文件)的类。spdlog自带的几种sinks已经能满足日常需求,也可以派生其基类设计新的 sink 以满足特殊的需求。sink类主要使用的函数包括:
- set_pattern(const std::string&):设置日志输出格式。
- set_level(level_enum):设置日志输出的最低等级。
- log(log_msg):由logger自动调用,外部不会主动调用。
- logger:日志记录器,被顶层调用来输出日志的类。一个logger对象中存储有多个sink,当调用logger的日志输出函数时,logger会调用自身存储的所有sink对象的log(log_msg)函数进行输出。与自身的sink对应,spdlog也自带了几种logger。logger类主要使用的函数包括:
- set_pattern(const std::string&):设置logger包括的所有sink的日志输出内容格式。
- set_level(level_enum):设置logger日志输出最低等级,如果logger包含的sink没有设置日志等级的话,则会为其设置日志等级。
- log(level_enum level, log_msg content):按照level等级进行输出content,logger其中日志输出最低等级小于或等于level的sink会执行输出操作。
- info(content, arg1, arg2…):按照trace等级进行输出,输出内容由content与后面的采纳数格式化组成。荣磊的函数还包括debug/trace/warn…。
- st/mt:对象版本,spdlog 中 logger 对象和 sink 对象都有两种版本,一种是以 st 结尾的单线程版本,以及以 mt 结尾的多线程版本。
- st:单线程版本,不用加锁,效率更高。
- mt:多线程版本,用于多线程程序是线程安全的。
相关文章:
C++ 日志库 spdlog 使用教程
Spdlog是一个快速、异步、线程安全的C日志库,他可以方便地记录应用程序的运行状态,并提供多种输出格式。官网:https://github.com/gabime/spdlog 安装教程可以参考:https://blog.csdn.net/Harrytsz/article/details/144887297 S…...
`http_port_t
http_port_t 是 SELinux(Security-Enhanced Linux)中的一种端口类型标签,用于标识哪些端口可以被 HTTP 和 HTTPS 服务使用。SELinux 是一种强制访问控制(MAC)安全模块,它通过定义安全策略来限制进程对系统资…...
SpringBoot中实现拦截器和过滤器
【SpringBoot中实现过滤器和拦截器】 1.过滤器和拦截器简述 过滤器Filter和拦截器Interceptor,在功能方面很类似,但在具体实现方面差距还是比较大的。 2.过滤器的配置 2.1 自定义过滤器,实现Filter接口(SpringBoot 3.0 开始,jak…...
不锈钢均温板结合强力粘合技术革新手机内部架构
摘要: 本文介绍了一种创新性的手机内部架构设计方案,其中不锈钢均温板不仅作为高效的散热元件,还充当了手机中框的主要结构件。通过使用强力不可拆胶水将主板、尾插和其他关键部件直接粘合到均温板上,该方案实现了更为紧密的热耦合…...
Docker安装使用
文章目录 Docker安装Docker的基础使用搜索&拉取镜像 Docker的生命周期利用Docker切换不同OSDocker容器 镜像的保存&分享Docker存储Docker网络 Docker安装 更新apt索引 sudo apt-get update添加Docker所需要的依赖 apt-get install ca-certificates curl gnupg lsb-r…...
React 如何进行路由变化监听
一、使用react-router库(以react-router-dom为例) 1. 历史(history)对象监听 1.1 原理 react-router内部使用history对象来管理路由历史记录。可以通过访问history对象来监听路由变化。在基于类的组件中,可以通过组…...
Unity UGUI使用技巧与经验总结(不定期更新)
Text自动缩放参考连接: Unity -UGUI中Text文本框的自动调整,字体大小的自适应调节_unity添加的字体大小锁定-CSDN博客 Toggle按钮选择时,显示对应的UI界面: 为Toggle组件的On Value Change事件添加对需要显示的对象的SetActive…...
中国乡镇界shp全境arcgis格式shp数据乡镇名称下载后内容测评
下载乡镇界shp链接:https://download.csdn.net/download/zhongguonanren99/19354855 标题中的“中国乡镇界shp全境arcgis格式shp数据乡镇名称2012年”揭示了这个数据集的核心内容。它是一个地理信息系统(GIS)数据,具体来说是使用…...
第 31 章 - 源码篇 - Elasticsearch 写入流程深入分析
写入源码分析 接收与处理 请求首先会被 Netty4HttpServerTransport 接收,接着交由 RestController 进行路由分发。 private void tryAllHandlers(final RestRequest request, final RestChannel channel, final ThreadContext threadContext) throws Exception {…...
node.js下载、安装、设置国内镜像源(永久)(Windows11)
目录 node-v20.18.0-x64 工具下载安装设置国内镜像源(永久) node-v20.18.0-x64 工具 系统:Windows 11 下载 官网https://nodejs.org/zh-cn/download/package-manager 版本我是跟着老师选的node-v20.18.0-x64如图选择 Windows、x64、v2…...
小于n的最大数 - 贪心算法 - C++
字节经典面试题 给定一个整数n,并从1~9中给定若干个可以使用的数字,根据上述两个条件,得到每一位都为给定可使用数字的、最大的小于整数n的数,例如,给定可以使用的数字为 {2,3,8} 三个数:给定 n3589&#x…...
【顶刊TPAMI 2025】多头编码(MHE)之极限分类 Part 3:算法实现
目录 1 三种多头编码(MHE)实现1.1 多头乘积(MHP)1.2 多头级联(MHC)1.3 多头采样(MHS)1.4 标签分解策略 论文:Multi-Head Encoding for Extreme Label Classification 作者…...
解决CentOS 8 YUM源更新后报错问题:无法下载AppStream仓库元数据
背景介绍 在尝试更新CentOS 8的YUM源以使用阿里云镜像时,遇到了Failed to download metadata for repo appstream的错误。此错误通常出现在执行yum clean all && yum makecache命令之后,表明系统无法从指定的URL获取AppStream仓库的元数据。本文…...
[python3]Excel解析库-openpyxl
https://openpyxl.readthedocs.io/en/stable/ openpyxl 是一个用于读写 Excel 2010 xlsx/xlsm/xltx/xltm 文件的 Python 库。它允许开发者创建、修改和保存电子表格,而无需依赖 Microsoft Excel 软件本身。openpyxl 支持读取和写入 Excel 的工作簿(Work…...
Docker 远程访问完整配置教程以及核心参数理解
Docker 远程访问完整配置教程 以下是配置 Docker 支持远程访问的完整教程,包括参数说明、配置修改、云服务器安全组设置、主机防火墙配置,以及验证远程访问的详细步骤。 1. 理解 -H fd:// 参数的作用(理解了以后容易理解后面的操作ÿ…...
王老吉药业SRM系统上线 携手隆道共启战略合作新篇章
12月27日,广州王老吉药业股份有限公司(简称“王老吉药业”)SRM项目上线启动会,在王老吉科普教育基地——“吉园”隆重举行。广药集团纪委主任陈耕、王老吉药业总工程师黄晓丹、隆道公司总裁吴树贵、项目经理赵耀、供应商代表郭伟及…...
MyBatis 配置文件全解析
一、MyBatis 配置文件为何至关重要? 在 Java 后端开发领域,MyBatis 作为一款广受欢迎的持久层框架,极大地简化了数据库操作。而 MyBatis 配置文件,恰似整个框架的 “神经中枢”,掌控着其运行的方方面面,对…...
unity学习6:unity的3D项目的基本界面和菜单
目录 1 unity界面的基本认识 1.1 file 文件 1.2 edit 编辑/操作 1.3 Assets 1.4 gameobject 游戏对象 1.5 组件 1.6 windows 2 这些部分之间的关系 2.1 关联1: Assets & Project 2.2 关联2:gameobject & component 2.3 关联3…...
企业二要素如何用C#实现
一、什么是企业二要素? 企业二要素,通过输入统一社会信用代码、企业名称或统一社会信用代码、法人名称,验证两者是否匹配一致。 二、企业二要素适用哪些场景? 例如:信用与金融领域 1.信用评级:信用评级…...
中科院空天院无人机视觉语言导航新基准!AeroVerse:模拟、预训练、微调和评估空中无人机具身世界模型的测试基准
作者: Fanglong Yao, Yuanchang Yue, Youzhi Liu, Xian Sun, Kun Fu 单位:中国科学院空天信息创新研究院网络信息系统技术重点实验室,中国科学院大学电子电气与通信工程学院 原文链接: AeroVerse: UAV-Agent Benchmark Suite fo…...
D3KeyHelper:暗黑3玩家的终极按键助手,告别手酸轻松刷图
D3KeyHelper:暗黑3玩家的终极按键助手,告别手酸轻松刷图 【免费下载链接】D3keyHelper D3KeyHelper是一个有图形界面,可自定义配置的暗黑3鼠标宏工具。 项目地址: https://gitcode.com/gh_mirrors/d3/D3keyHelper 还在为暗黑破坏神3中…...
5步掌握Audiveris乐谱识别:从扫描到编辑的完整指南
5步掌握Audiveris乐谱识别:从扫描到编辑的完整指南 【免费下载链接】audiveris Latest generation of Audiveris OMR engine 项目地址: https://gitcode.com/gh_mirrors/au/audiveris 你是否曾面对堆积如山的纸质乐谱,渴望将它们转换为可编辑的数…...
城通网盘直连解析工具终极指南:3大技术突破实现高速下载
城通网盘直连解析工具终极指南:3大技术突破实现高速下载 【免费下载链接】ctfileGet 获取城通网盘一次性直连地址 项目地址: https://gitcode.com/gh_mirrors/ct/ctfileGet 你是否曾经面对城通网盘的龟速下载而束手无策?每次下载文件都要经历漫长…...
HTML----列表与表格
一、列表标签1.<ul>:无序列表标签,用来放没有先后顺序的并列内容2.<ol>:有序列表标签,用来存放有明确先后顺序的步骤内容3.<li>:列表项,不管是<ul>还是<ol>里面都只能放.<li>,不能直接写文字…...
蓝牙耳机连接背后的秘密:SDP协议在A2DP配对中的关键作用
蓝牙耳机连接背后的秘密:SDP协议在A2DP配对中的关键作用 每次打开蓝牙耳机,手机总能自动识别并恢复上次的音量设置和播放控制——这种无缝体验背后,隐藏着一套精妙的协议对话机制。就像餐厅老顾客无需重复点单,蓝牙设备间的"…...
SecGPT-14B惊艳效果:对同一CVE编号,SecGPT生成厂商通告、PoC分析、修复验证三段式内容
SecGPT-14B惊艳效果:对同一CVE编号,SecGPT生成厂商通告、PoC分析、修复验证三段式内容 1. 网络安全分析新范式 在网络安全领域,漏洞分析通常需要安全专家投入大量时间查阅资料、编写报告。传统流程中,厂商通告、漏洞利用分析(Po…...
【ArkUI】简述 UIAbility 组件的生命周期、启动模式和基本用法
一、UIAbility 组件概述 UIAbility 组件是一种包含 UI 的应用组件,主要用于和用户交互。例如,图库类应用可以在 UIAbility 组件中展示图片瀑布流。 UIAbility 的设计理念是:支持应用组件级的跨端迁移和多端协同。支持多设备和多窗口形态。 UIAbility 组件是系统调度的基本单…...
告别两阶段!用单个冻结的ConvNeXt-Large CLIP,7.5倍速搞定开放词汇分割(附代码)
7.5倍速开放词汇分割实战:FC-CLIP架构设计与工程实现 当你在深夜调试两阶段分割模型时,是否曾对着显存不足的报错信息陷入沉思?开放词汇分割任务对算法工程师提出了双重挑战:既要处理任意类别的语义理解,又要应对高分辨…...
手把手教你用Coze工作流给公众号文章做AI摘要:从抓取、总结到飞书推送的完整避坑指南
手把手教你用Coze工作流打造智能摘要系统:从公众号到飞书的自动化实践 每天打开微信,订阅号里堆积的未读文章数字像雪球一样越滚越大——这种信息焦虑已经成为现代人的通病。我们既不想错过行业动态,又苦于时间有限无法逐篇阅读。传统的人工筛…...
在 BitaHub 部署 FaceFusion:快速搭建你的 AI 换脸系统
一.背景介绍随着 AIGC 技术的快速发展,AI 换脸(Face Swapping)正逐渐从幕后走向前台,成为短视频创作、虚拟人构建、娱乐营销乃至影视制作的重要工具。尤其是视频博主、内容创作者和开发者,对换脸技术的需求不断增长&am…...
