spdlog: 高性能C++日志库

spdlog是一个高性能,超高速,零配置的C++日志库,它旨在提供简洁的API和丰富的功能,同时保持高性能的日志记录.它支持多种输出目标,个刷选项,线程安全以及异步日志记录.

spdlog的特点介绍:

  • 高性能: spdlog专为速度而设计,即使在高负载情况下也能保持良好的性能.
  • 零配置: 无需复杂的配置,只需要包含头文件即可在项目中使用.
  • 异步日志: 支持异步日志记录,减少对主线程的影响.
  • 格式化: 支持自定义日志的格式化,包括时间戳,线程id,日志级别等等.
  • 多平台: 跨平台兼容,支持Windows,Linux,maxOS等操作系统.
  • 丰富的API: 提供丰富的日志级别和操作符重载,方便记录各类类型的日志.

安装

fedora系统下安装:

shell 复制代码
sudo dnf install -y spdlog-devel

源码安装

shell 复制代码
$ git clone https://github.com/gabime/spdlog.git
$ cd spdlog && mkdir build && cd build
$ cmake .. && cmake --build .

标准日志输出

  1. 添加头文件#include <spdlog/spdlog.h>
  2. 创建日志对象 std::shared_ptr<logger> stdout_color_mt( const std::string &logger_name, color_mode mode = color_mode::automatic);
  3. 设置日志输出等级void set_level(level::level_enum log_level);
  4. 设置日志输出格式void set_pattern(std::string pattern, pattern_time_type time_type);
  5. 输出日志

演示

C++ 复制代码
#include <iostream>
// 1. 添加头文件
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>


int main(int argc,char* argv[])
{
    // 2. 创建日志对象
    auto logger = spdlog::stdout_color_mt("logger");
    // 3. 设置日志输出等级
    logger->set_level(spdlog::level::debug);
    // 4. 设置日志输出格式
    logger->set_pattern("[%H:%M:%S ][%-7l]:%v");
    // 5. 输出日志
    logger->debug("{}我是日志","test");
    logger->info("{}我是日志","test");
    logger->warn("{}我是日志","test");
    logger->error("{}我是日志","test");
    return 0;
}

打印:

txt 复制代码
❯ ./sync
[17:10:46 ][debug  ]:test我是日志
[17:10:46 ][info   ]:test我是日志
[17:10:46 ][warning]:test我是日志
[17:10:46 ][error  ]:test我是日志

输出到文件

c++ 复制代码
//指定⽂件
template<typename Factory = spdlog::synchronous_factory>
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 = {}

演示

c++ 复制代码
#include <iostream>
// 1. 添加头文件
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>


int main(int argc,char* argv[])
{
    // 2. 创建日志对象
    // auto logger = spdlog::stdout_color_mt("logger");
    auto logger = spdlog::basic_logger_mt("logger","./log.log");
    // 3. 设置日志输出等级
    logger->set_level(spdlog::level::debug);
    // 4. 设置日志输出格式
    logger->set_pattern("[%H:%M:%S ][%-7l]:%v");
    // 5. 输出日志
    logger->debug("{}我是日志","test");
    logger->info("{}我是日志","test");
    logger->warn("{}我是日志","test");
    logger->error("{}我是日志","test");
    return 0;

循环文件输出

c++ 复制代码
//循环⽂件
template<typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> rotating_logger_mt(
const std::string &logger_name,
const filename_t &filename,
size_t max_file_size,
size_t max_files,
bool rotate_on_open = false)

演示

c++ 复制代码
#include <iostream>
// 1. 添加头文件
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/sinks/rotating_file_sink.h>


int main(int argc,char* argv[])
{
    // 2. 创建日志对象
    // auto logger = spdlog::stdout_color_mt("logger");
    // auto logger = spdlog::basic_logger_mt("logger","./log.log");
    auto logger = spdlog::rotating_logger_mt("logger","./rotating.log",1024,3);
    // 3. 设置日志输出等级
    logger->set_level(spdlog::level::debug);
    // 4. 设置日志输出格式
    logger->set_pattern("[%H:%M:%S ][%-7l]:%v");
    // 5. 输出日志
    for(int i = 0;i<512;++i)
    {
        logger->error("test -- {}",i);
    }
    return 0;
}

异步输出

c++ 复制代码
using async_factory = async_factory_impl<async_overflow_policy::block>;

演示

c++ 复制代码
#include <iostream>
// 1. 添加头文件
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/sinks/rotating_file_sink.h>
#include <spdlog/async.h>


int main(int argc,char* argv[])
{
    // 2. 创建日志对象
    // auto logger = spdlog::stdout_color_mt("logger");
    // auto logger = spdlog::basic_logger_mt("logger","./log.log");
    auto logger = spdlog::rotating_logger_mt<spdlog::async_factory>("logger","./rotating_async.log",1024,3);
    // 3. 设置日志输出等级
    logger->set_level(spdlog::level::debug);
    // 4. 设置日志输出格式
    logger->set_pattern("[%H:%M:%S ][%-7l]:%v");
    // 5. 输出日志
    for(int i = 0;i<512;++i)
    {
        logger->error("test -- {}",i);
    }
    return 0;
}

介绍flush_on函数

spdlog为了提升性能,默认会把日志内容先存入内存缓冲区内,而不是立即写入文件/控制台等目标.

flush_on() 的作用就是:指定当日志级别达到某个阈值时,强制触发一次刷新操作,确保该级别及更高级别的日志能立刻落地,不会留在缓冲区里。

flush_on() 的具体作用

它的核心功能是设置 "自动刷新的日志级别阈值"

  • 当调用 logger->flush_on(spdlog::level::warn); 时,意味着:
    • 只要记录 warnerrorcritical 级别的日志,spdlog 就会立刻把缓冲区里的所有日志(包括之前的低级别日志,如 info/debug)刷新到目标;
  • 而低于该级别的日志(如 info/debug/trace),仍会按照默认策略缓冲(比如缓冲区满了、程序结束时才刷新)。

介绍daily_logger_format_mt函数

spdlog::daily_logger_mt 是 spdlog 中专门用于按日期自动分割日志文件的多线程安全日志器

daily_logger_mt(daily + logger + mt = 每日日志器 + 多线程安全)的核心功能是:

  • 日期 + 指定时间点自动创建新的日志文件,避免单个日志文件过大;
  • 天生支持多线程(mt = multi-thread),可在多线程程序中安全使用;
  • 继承了 spdlog 所有基础特性(如日志级别、刷新策略、格式化等)。

比如你设置每天凌晨 2 点分割日志,那么:

  • 2026-01-23 02:00 前的日志会写入 app_2026-01-23.log
  • 2026-01-24 02:00 会自动创建 app_2026-01-24.log,后续日志写入新文件。

二次封装

为什么要进行二次封装

  • 避免单例的锁冲突,直接创建一个全局的线程安全的日志器进行使用.
  • 使用宏进行二次封装输出日志的文件名和行号
  • 封装出一个初始化接口,便于使用:调试模式则输出标准输出,否则输出到文件中.

思想:

封装出一个全局接口,用户进行日志器的创建与初始化,根据不同的运行模式选择不同的标准输出方式.

c++ 复制代码
#pragma once

#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/sinks/rotating_file_sink.h>
#include <spdlog/sinks/daily_file_sink.h>
#include <spdlog/async.h>

// 定义全局的日志对象
std::shared_ptr<spdlog::logger> g_defult_logger;
/**
 * @description 初始化日志系统
 * @param 
 * mode:运行模式
 * fileName:输出日志的路径
 * level:发布模式下的日志输出等级
 */
void init_logger(bool mode, std::string &fileName, int32_t level)
{
    // mode为真表示发布模式,mode为假表示调试模式
    if (mode == false)
    {
        //打印到标准输出
        g_defult_logger = spdlog::stdout_color_mt<spdlog::async_factory>("g_default_logger");
        g_defult_logger->set_level(spdlog::level::level_enum::trace);
    }
    else
    {
        //打印到文件中
        g_defult_logger = spdlog::daily_logger_format_mt<spdlog::async_factory>("g_default_logger", fileName, 0, 0);
        g_defult_logger->set_level(static_cast<spdlog::level::level_enum>(level));
        g_defult_logger->flush_on(spdlog::level::warn);
    }
    //日志输出格式
    g_defult_logger->set_pattern("[%Y-%m-%d | %H:%M:%S] [%-7l]-> %v");
}

#define LOG_TRACE(format,...) g_defult_logger->trace("[{}:{}]: " format,__FILE__,__LINE__,##__VA_ARGS__);
#define LOG_DEBUG(format,...) g_defult_logger->debug("[{}:{}]: " format,__FILE__,__LINE__,##__VA_ARGS__);
#define LOG_INFO(format,...) g_defult_logger->info("[{}:{}]: " format,__FILE__,__LINE__,##__VA_ARGS__);
#define LOG_WARN(format,...) g_defult_logger->warn("[{}:{}]: " format,__FILE__,__LINE__,##__VA_ARGS__);
#define LOG_ERROR(format,...) g_defult_logger->error("[{}:{}]: " format,__FILE__,__LINE__,##__VA_ARGS__);
#define LOG_FATAL(format,...) g_defult_logger->critical("[{}:{}]: " format,__FILE__,__LINE__,##__VA_ARGS__);
相关推荐
それども2 小时前
线程池阻塞队列选择ArrayBlockingQueue与LinkedBlockingQueue区别
java·开发语言·网络协议
bugu___2 小时前
仿muduo库实现并发服务器(2)
运维·服务器·c++
沛沛老爹2 小时前
从Web到AI:Agent Skills安全架构实战——权限控制与数据保护的Java+Vue全栈方案
java·开发语言·前端·人工智能·llm·安全架构·rag
Remember_9932 小时前
文件系统与IO操作:深入解析与Java实践
java·开发语言·数据结构·ide·python·算法
a3158238062 小时前
TCP/IP协议的概述和面试要点
开发语言·php
REDcker2 小时前
OpenSSL 完整文档
c++·安全·github·c·openssl·后端开发
LYS_06182 小时前
RM专用赛事c型板IMU9轴解算(1)(对于IST8310和BMI088的直接使用)
c语言·开发语言
yubo05092 小时前
Python 包、模块、导入规则
开发语言·python
f狐0狸x2 小时前
C++ vector 从入门到上手:核心基本用法全解析
开发语言·c++