spdlog linux编译出错,spdlog 基本结构分析

没有检索到摘要

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

spdlog 基本结构分析

代码取自 V1.5.0, 代码堪称美学。

spdlog 是一个只有头文件的C++日志库,速度非常快,扩展性很强,更重要的是 社区活跃,文档齐全。

使用

{fmt} 的格式使用也需要熟悉一下,毕竟也进 C++20 了,什么垃圾流就快扫进历史的垃圾堆吧.

分析

这里选择了三个点来做分析:

提供的 日志格式 非常丰富,并且允许用户自定义需要的格式。

对日志文件的类型也做了充分扩展,支持控制台,普通文件,按大小滚动文件,按时间滚动文件,如果不能满足需要,可以自己扩展格式,见 spdlog/sinks/base_sink.h。

支持单/多线程,异步/同步,阻塞非阻塞模式。

spdlog 的代码结构如下:

spdlog

├─example 用法代码

├─include 实现目录

│ └─spdlog

│ ├─details 功能函数目录

│ ├─fmt {fmt} 库目录

│ ├─sinks 落地文件格式实现

│ └─*.h 异步模式,日志库接口等实现

├─src .cpp 文件,组成编译模块生成静态库使用

├─test 测试代码

基本逻辑结构如下:

47309b8149b93dc295fb38c11b4a6511.png

有几个比较重要的文件:

spdlog/spdlog.h 为日志库接口,提供日志宏的属性控制函数。

spdlog/logger.h 为日志管理器,为前后端连接的枢纽。

spdlog/async.h 为异步模式接口。

spdlog/sinks/base_sink.h 为日志文件格式父类,后面所有的日志文件格式都是继承该类来实现不同功能。

spdlog/sinks/registry.h 用于登记所有的logger,及一些默认的属性,如日志格式、日志写入等级。

spdlog 接口

spdlog 总体而言提供了日志接口

spdlog::debug(), 默认的日志对象,使用默认的日志信息格式,输出至 stdout。

logger->debug(), 指定日志对象进行日志记录,输出至该日志对象对应的文件中。

SPDLOG_LOGGER_DEBUG(logger), SPDLOG_DEBUG(), 使用宏对以上两种接口进行包装,产生的日志格式包含 文件、函数、行。

提供的一些落地的文件类型:

标准输出

带颜色的标准输出(默认)

基本文件

可设定时间的滚动文件

可设定大小的滚动文件

过滤重复的日志

syslog 日志

这里简单提一下 sinks 的实现,所有落地文件的类型都是从 base_sink(忽略sink) 继承而来,提供了两个纯虚函数 sink_it_() 和 flush_(),这样一来,需要扩展的类型文件只需要实现两个函数,很大的简化了扩展的流程。而单/多线程通过模板来确定是否需要使用互斥量来保持同步,也算是比较有意思的一个实现了:

// 例子使用 base_file_sink

using basic_file_sink_mt = basic_file_sink<:mutex>;

using basic_file_sink_st = basic_file_sink<:null_mutex>;

struct null_mutex

{

void lock() const {}

void unlock() const {}

bool try_lock() const

{

return true;

}

};

template

void SPDLOG_INLINE spdlog::sinks::base_sink::log(const details::log_msg &msg)

{

std::lock_guard lock(mutex_);

sink_it_(msg);

}

如果需要使用多线程模式,就使用 std::mutex,如果是单线程,我们就不需要互斥来同步,这里实现一个空的互斥量类,就使得 log() 的代码完全不需要修改了,也提高了内聚性。

spdlog 默认使用同步模式,也可以设置异步模式,异步模式会创建一个线程池,线程池大小可以自行设置,默认为1,该线程池所有者为 details::registry::instance(). 后台的大小可以设置的 多生产者多消费者队列 默认为阻塞模式,也可以设置为非阻塞,不过这个非阻塞的处理非常简单粗暴,就是简单的丢弃最老的日志,推荐是不要这样设置滴,一般产生阻塞的情况大概是磁盘IO打满了,出现这个情况一般是别的地方出问题了。

details::registry 管理所有的日志对象

使用 将日志对象和其名称对应起来,后面使用的时候可以直接通过名称获取对应的日志对象。

保存全部日志对象的默认属性,可使用提供的属性控制接口改变所有的日志对象属性。

提供定时flush,spdlog 的文件操作具有缓冲区属性,为试日志信息及时落地,后台新生成一个flush线程,设置一个时间(单位:秒)定时唤醒一次进行 flush。

参考

{fmt}, A modern formatting library. 现代化的格式化库,速度快,使用简单,已经确定进入 C++20.

inline std::string RobotFormat(int level, const char *pformat, ...) { if (level > g_Logger->getLogLevel() || g_Logger->getLogLevel() == 9) { return std::string(""); } va_list argList; va_start(argList, pformat); char strBuf[MAX_LOG_SIZE] = {'\0'}; size_t num_of_chars = vsnprintf(strBuf, MAX_LOG_SIZE - 1, pformat, argList); va_end(argList); if(num_of_chars <= 0) { return std::string(""); } return std::string(strBuf); } #0 strlen () at ../sysdeps/arm/armv6t2/strlen.S:126 #1 0xb662827e in __vfprintf_internal (s=s@entry=0xaa268450, format=format@entry=0xb45291dc "handle time is out range (20*2ms, +)!!! handle_time_us = %ld, m_prev_handle_timestamp_us = %ld, curr_handle_timestamp_us = %ld, m_first_frame_ %s", ap=..., ap@entry=..., mode_flags=mode_flags@entry=0) at vfprintf-internal.c:1688 #2 0xb66339e6 in __vsnprintf_internal (string=0xaa268570 "handle time is out range (20*2ms, +)!!! handle_time_us = 0, m_prev_handle_timestamp_us = 54009, curr_handle_timestamp_us = 0, m_first_frame_ ", maxlen=<optimized out>, format=0xb45291dc "handle time is out range (20*2ms, +)!!! handle_time_us = %ld, m_prev_handle_timestamp_us = %ld, curr_handle_timestamp_us = %ld, m_first_frame_ %s", args=..., mode_flags=mode_flags@entry=0) at vsnprintf.c:114 #3 0xb6633a10 in ___vsnprintf (string=<optimized out>, maxlen=<optimized out>, format=<optimized out>, args=...) at vsnprintf.c:124 #4 0xb45efc94 in RobotFormat[abi:cxx11](int, char const*, ...) () from Plugins/libPeripheral.plg #5 0xb45245cc in communication::CSerialMessageHandle::handleSensorMessage(communication::CRobotPacket*) () from /home/lizewei/source/T10/robot2.0/build_ssd22d/bin/libStm32.so #6 0xb4525364 in communication::CSerialMessageHandle::handleMessage(communication::CRobotPacket*) () from /home/lizewei/source/T10/robot2.0/build_ssd22d/bin/libStm32.so #7 0xb45a0b38 in driver::Stm32Driver::readData() () from /home/lizewei/source/T10/robot2.0/build_ssd22d/bin/libDriver.so #8 0xb680e21a in std::execute_native_thread_routine (__p=0x14ebf08) at /home/meng/toolchain/build/snapshots/gcc.git~gcc-9_1_0-release/libstdc++-v3/src/c++11/thread.cc:80 #9 0xb65b1c00 in start_thread (arg=0x5b2bcd5) at pthread_create.c:479 #10 0xb667e61c in ?? () at ../sysdeps/unix/sysv/linux/arm/clone.S:73 from /opt/ssd22d/arm-buildroot-linux-gnueabihf/sysroot/lib/libc.so.6
最新发布
03-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值