【开源组件】spdlog日志库


前言

本文将介绍spdlog日志库的整体结构,并对实际使用该日志库的方法进行了分析。


一、spdlog介绍

spdlog 是一款高效的 C++ 日志库,它以其极高的性能和零成本的抽象而著称。spdlog 支持异步和同步日志记录,提供多种日志级别,并允许用户将日志输出到控制台、文件或自定义的接收器。

1.1 spdlog特征

spdlog 的性能特点使其在高性能应用中非常受欢迎

  • 极高的日志记录速度: spdlog 能够在每秒记录数百万条日志消息,这对于需要处理大量日志数据的应用来说是非常重要的。
  • 低内存占用: spdlog 的设计确保了即使在高负载下,它也能保持低内存占用。
  • 灵活的配置: 用户可以根据需要配置 spdlog,选择异步或同步日志记录,以及选择不同的日志级别和输出目标。

1.2 spdlog输出控制

  • 多种日志级别
    • trace、debug、info、warn、error,and critical
    • 设定最低日志级别,【开发阶段采用较低日志级别,发布阶段采用较高日志级别】
  • 多种输出目标: 用户可以将日志输出到控制台、文件或通过网络发送到远程服务器。
  • 格式化输出: spdlog 支持格式化输出,允许用户以结构化的方式输出日志消息。

1.3 spdlog处理流程

Spdlog 的流程非常简单,但是每个组件都扮演着重要的角色。
Loggers 负责记录日志消息;
Sinks 决定了日志消息的输出位置;
Formatters 负责将日志消息转换为特定格式;
Async Logger 异步地将日志消息写入到目标 Sink 中;
Registry 用于管理这些组件。

image.png

异步logger使用了线程池,默认一个线程。

可能采用多个logger,比如网络logger、本地logger、定制logger等

1.4 异步日志和同步日志区别

1.4.1 多线程使用日志库,跟同步和异步是否有关联?

没有什么关联,当同步打印日志时,但我们是使用的多线程,此时我们需要考虑使用互斥锁只允许一个线程操作。当异步打印日志时,那么执行异步操作的线程也需要考虑互斥的问题。

1.4.2 同一线程处理,是不是就是同步?

如果是当前线程处理,当然是同步的。但是如果只是获得完成通知,那么就只是协程上的同步。

二、异步日志库设计与实现

2.1 如何创建logger

// 生成默认的logger、sink等,该信息会输出到控制台!
spdlog::info("Welcome to spdlog!");

2.1.1 工厂方法创建

auto logger = spdlog::basic_logger_mt("basic", "basic.txt");
logger->info("hello world from basic_sink");
spdlog::get("basic")->info("hello world from basic_sink tool");

// 异步工厂
auto logger2 = spdlog::basic_logger_mt<spdlog::async_factory>("async_basic", "basic.txt");
logger2->info("hello world from basic_sink");

工厂模式的好处:
某一个对象创建较复杂,将创建过程对用户进行屏蔽。

template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> basic_logger_mt(const std::string &logger_name,
                                               const filename_t &filename,
                                               bool truncate = false,
                                               const file_event_handlers &event_handlers = {}) {
    return Factory::template create<sinks::basic_file_sink_mt>(logger_name, filename, truncate,
                                                               event_handlers);
}

该工厂方法屏蔽了logger对register和sink等对象的依赖。

2.1.2 手动创建

auto sink1 = std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>();
auto sink2 = std::make_shared<spdlog::sinks::basic_file_sink_mt>("hand.txt", true);

auto logger3 = std::make_shared<spdlog::logger>("self");
logger3->sinks().push_back(sink1);
logger3->sinks().push_back(sink2);
spdlog::register_logger(logger3); // 将logger需要手动注册到register中
logger3->info("multi sinks");

手动创建可以绑定多个sink。

注册logger,目的是为了全局访问

2.2 如何创建sink

  1. sink_it_
template <typename Mutex>
SPDLOG_INLINE void basic_file_sink<Mutex>::sink_it_(const details::log_msg &msg) {
    memory_buf_t formatted;
    base_sink<Mutex>::formatter_->format(msg, formatted);
    file_helper_.write(formatted);
}

是为了写到用户态的缓冲区

  1. flush_
template <typename Mutex>
SPDLOG_INLINE void basic_file_sink<Mutex>::flush_() {
    file_helper_.flush();
}

是写到内核态的发送缓冲区

2.3 如何自定义格式化

set_pattern

eg.

sink1->set_pattern("[%^%L%$] %v");

2.4 如何创建异步日志

// 1. 使用spdlog::async_factory模板参数
auto logger2 = spdlog::basic_logger_mt<spdlog::async_factory>("async_basic", "basic.txt");

// 2. 使用spdlog::create_async<Sink>
spdlog::create_async<spdlog::sinks::basic_file_sink_mt>("async", "hello.txt", true);

// 3. 使用spdlog::create_async_nb<Sink>,队列是非阻塞的。

// 4. 使用spdlog::async_logger
auto async_logger = std::make_shared<spdlog::async_logger>("tp", spdlog::sinks_init_list{sink1, sink2}, spdlog::thread_pool());

aysnc_logger->info("async_logger");

image.png

2.5 刷新策略

// 间隔flush,需要线程安全的logger
spdlog::flush_every(std::chrono::seconds(5))

// 条件flush,设置最小日志等级触发自动flush
logger->flush_on(spdlog::level::err);

// 手动flush,如果是异步的,将发出一个flush的消息
logger->flush

三、日志的作用

  1. 追踪程序运行状态
  2. 出现问题提供现场运行信息

总结

本文总结了spdlog日志库的整体结构,并列举实际使用该日志库的方法。

参考链接:
https://github.com/0voice

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值