← 返回主页
spdlog 使用指南
spdlog 是一个快速、仅头文件的 C++ 日志库,提供了丰富的日志功能,包括多线程安全、异步日志记录、多种输出格式和自定义格式化。它被广泛应用于各种 C++ 项目中。
📦 安装
通过 vcpkg 安装(推荐)
vcpkg install spdlog
通过 Conan 安装
conan install spdlog/1.12.0@
从源码编译
git clone https://github.com/gabime/spdlog.git
cd spdlog
mkdir build && cd build
cmake .. -DSPDLOG_BUILD_EXAMPLE=ON
cmake --build . --parallel
头文件方式使用
#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>
🚀 基础使用
Hello World
#include <spdlog/spdlog.h>
int main() {
// 控制台输出
spdlog::info("Hello, spdlog!");
spdlog::warn("Warning message");
spdlog::error("Error message");
spdlog::critical("Critical error");
return 0;
}
不同级别的日志
#include <spdlog/spdlog.h>
int main() {
// 设置日志级别
spdlog::set_level(spdlog::level::debug);
spdlog::trace("Trace message");
spdlog::debug("Debug message");
spdlog::info("Info message");
spdlog::warn("Warning message");
spdlog::error("Error message");
spdlog::critical("Critical message");
return 0;
}
格式化输出
#include <spdlog/spdlog.h>
#include <string>
int main() {
// 使用占位符格式化
int count = 42;
std::string name = "spdlog";
spdlog::info("Count: {}", count);
spdlog::info("Library: {}", name);
spdlog::info("Hello, {}! You have {} messages.", name, count);
// 多参数格式化
spdlog::info("User: {}, Age: {}, Score: {}", "Alice", 25, 95.5);
return 0;
}
📝 输出到文件
创建文件日志器
#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>
int main() {
try {
// 创建一个文件日志器
auto logger = spdlog::basic_logger_mt("basic_logger", "logs/basic.txt");
// 设置日志级别
logger->set_level(spdlog::level::debug);
// 记录日志
logger->info("Log to file: {}", "Hello");
logger->warn("This is a warning");
logger->error("This is an error");
// 刷新所有日志器
spdlog::shutdown();
}
catch (const spdlog::spdlog_ex& ex) {
spdlog::error("Log init failed: {}", ex.what());
}
return 0;
}
每日滚动文件
#include <spdlog/spdlog.h>
#include <spdlog/sinks/daily_file_sink.h>
int main() {
try {
// 创建每日滚动文件日志器
auto logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
logger->info("Daily log entry");
logger->warn("Warning in daily log");
spdlog::shutdown();
}
catch (const spdlog::spdlog_ex& ex) {
spdlog::error("Log init failed: {}", ex.what());
}
return 0;
}
按大小滚动文件
#include <spdlog/spdlog.h>
#include <spdlog/sinks/rotating_file_sink.h>
int main() {
try {
// 创建按大小滚动文件日志器(5MB,保留3个文件)
auto logger = spdlog::rotating_logger_mt("rotating_logger", "logs/rotating.txt", 1024 * 1024 * 5, 3);
logger->info("Rotating log entry");
logger->warn("Warning in rotating log");
spdlog::shutdown();
}
catch (const spdlog::spdlog_ex& ex) {
spdlog::error("Log init failed: {}", ex.what());
}
return 0;
}
🔄 多输出目标
同时输出到控制台和文件
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
int main() {
try {
// 创建控制台和文件 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/multisink.txt");
// 创建多 sink 日志器
spdlog::sinks_init_list sink_list = {console_sink, file_sink};
auto logger = std::make_shared<spdlog::logger>("multi_sink", sink_list);
// 注册日志器
spdlog::register_logger(logger);
// 输出日志(同时到控制台和文件)
logger->info("This goes to both console and file");
logger->warn("Warning message");
spdlog::shutdown();
}
catch (const spdlog::spdlog_ex& ex) {
spdlog::error("Log init failed: {}", ex.what());
}
return 0;
}
⚡ 异步日志
使用异步日志器
#include <spdlog/spdlog.h>
#include <spdlog/async.h>
#include <spdlog/sinks/basic_file_sink.h>
int main() {
try {
// 创建异步日志器(队列大小8192)
auto async_logger = spdlog::basic_logger_mt<spdlog::async_factory>(
"async_logger",
"logs/async.txt"
);
async_logger->info("Async log message");
async_logger->warn("Async warning");
async_logger->error("Async error");
spdlog::shutdown();
}
catch (const spdlog::spdlog_ex& ex) {
spdlog::error("Log init failed: {}", ex.what());
}
return 0;
}
异步日志配置
#include <spdlog/spdlog.h>
#include <spdlog/async.h>
int main() {
try {
// 配置异步日志器
spdlog::init_thread_pool(8192, 1); // 队列大小8192,1个线程
auto sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/async_config.txt");
auto logger = std::make_shared<spdlog::async_logger>(
"async_config",
sink,
spdlog::thread_pool()
);
spdlog::register_logger(logger);
logger->info("Async configured log");
spdlog::shutdown();
}
catch (const spdlog::spdlog_ex& ex) {
spdlog::error("Log init failed: {}", ex.what());
}
return 0;
}
🎨 自定义格式
自定义日志格式
#include <spdlog/spdlog.h>
#include <spdlog/pattern_formatter.h>
int main() {
// 设置全局格式
spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%n] [%^%l%$] [thread %t] %v");
spdlog::info("Formatted log message");
spdlog::warn("Warning with custom format");
// 为特定日志器设置格式
auto logger = spdlog::basic_logger_mt("custom", "logs/custom.txt");
logger->set_pattern("[%Y-%m-%d] [%l] %v");
logger->info("Custom format");
spdlog::shutdown();
return 0;
}
常用格式标识符
| 标识符 |
说明 |
%v |
实际的消息文本 |
%t |
线程ID |
%P |
进程ID |
%n |
日志器名称 |
%l |
日志级别(文本) |
%L |
日志级别(简写) |
%Y-%m-%d %H:%M:%S |
日期时间 |
%e |
毫秒 |
%f |
微秒 |
%s |
源文件名 |
%# |
源代码行号 |
%! |
函数名 |
💼 实际应用示例
多模块日志系统
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
class LoggerFactory {
public:
static std::shared_ptr<spdlog::logger> getLogger(const std::string& name) {
// 如果日志器已存在,直接返回
if (auto logger = spdlog::get(name)) {
return logger;
}
// 创建新的日志器
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/" + name + ".log"
);
auto logger = std::make_shared<spdlog::logger>(
name,
spdlog::sinks_init_list{console_sink, file_sink}
);
logger->set_level(spdlog::level::debug);
logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%n] [%^%l%$] %v");
spdlog::register_logger(logger);
return logger;
}
};
int main() {
try {
// 获取不同模块的日志器
auto db_logger = LoggerFactory::getLogger("database");
auto network_logger = LoggerFactory::getLogger("network");
auto app_logger = LoggerFactory::getLogger("application");
db_logger->info("Database connection established");
network_logger->info("Network initialized on port 8080");
app_logger->info("Application started");
db_logger->warn("Slow query detected");
network_logger->error("Connection timeout");
spdlog::shutdown();
}
catch (const spdlog::spdlog_ex& ex) {
spdlog::error("Log init failed: {}", ex.what());
}
return 0;
}
📋 日志级别速查
| 级别 |
数值 |
说明 |
trace |
0 |
最详细的跟踪信息 |
debug |
1 |
调试信息 |
info |
2 |
一般信息 |
warn |
3 |
警告信息 |
error |
4 |
错误信息 |
critical |
5 |
严重错误 |
off |
6 |
关闭日志 |
💡 提示: spdlog 是线程安全的,可以在多线程环境中安全使用。异步日志模式可以显著提高性能,特别是在高并发场景下。
⚠️ 注意:
- 使用完毕后记得调用
spdlog::shutdown() 刷新所有日志器
- 在程序退出前要确保所有日志都已写入磁盘
- 异步日志的队列大小需要根据实际需求调整
🔗 参考资料