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…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...

C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...