文章目录
1. 摘要
选一款日志工具,我们一般都考虑下面几个问题:
- 是否支持日志文件大小设置和循环存储?
- 是否支持异步存储?
- 是否支持日志等级配置?
spdlog 完美解决上面的问题,它是一款高性能的 C++ 日志库,专为低延迟和高吞吐量的日志记录需求设计。它支持多线程、异步日志、多种日志格式和输出目标,并且易于集成和使用。
2. 安装和使用
2.1 获取 spdlog
spdlog 是一个开源库,可以通过以下方式获取:
- GitHub 仓库:从 spdlog GitHub 克隆或下载源码。
git clone https://github.com/gabime/spdlog.git
- 包管理器:通过 vcpkg、Conan 等包管理器安装。
- vcpkg:
vcpkg install spdlog
- Conan:
conan install spdlog/1.x.x
2.2 编译 spdlog
spdlog 是一个仅有头文件的库(header-only),因此无需单独编译。只需将 include 目录添加到你的项目中即可。
如果需要使用异步日志功能,spdlog 依赖于一个单独的编译单元(spdlog.cpp),此时需要编译该文件:
g++ -std=c++11 -Iinclude -c src/spdlog.cpp -o spdlog.o
2.3 使用 spdlog
以下是一个简单的使用示例:
#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h" // 文件输出
#include "spdlog/sinks/stdout_color_sinks.h" // 控制台输出
int main() {
// 创建一个控制台日志器
auto console_logger = spdlog::stdout_color_mt("console");
console_logger->info("Welcome to spdlog!");
// 创建一个文件日志器
auto file_logger = spdlog::basic_logger_mt("file_logger", "logs/basic-log.txt");
file_logger->info("This message will be written to a file.");
// 设置全局日志级别
spdlog::set_level(spdlog::level::debug);
// 使用格式化日志
spdlog::info("Hello, {}!", "world");
spdlog::warn("This is a warning message.");
spdlog::error("This is an error message.");
// 刷新日志(确保所有日志被写入)
spdlog::shutdown();
return 0;
}
2.4 log 等级
spdlog 的日志等级用于区分日志消息的重要性或严重程度。它定义了多个日志级别,从最详细的跟踪信息到最严重的错误信息。以下是 spdlog 支持的日志等级及其含义:
enum level_enum : int {
trace = SPDLOG_LEVEL_TRACE, // 最详细的日志信息,通常用于调试或跟踪程序的执行流程。
debug = SPDLOG_LEVEL_DEBUG, // 调试信息,用于开发阶段排查问题。
info = SPDLOG_LEVEL_INFO, // 常规信息,用于记录程序的正常运行状态。
warn = SPDLOG_LEVEL_WARN, // 警告信息,表示可能存在问题,但不会影响程序运行。
err = SPDLOG_LEVEL_ERROR, // 错误信息,表示发生了错误,可能会影响程序的功能。
critical = SPDLOG_LEVEL_CRITICAL, // 严重错误信息,表示发生了致命错误,可能导致程序崩溃或无法继续运行。
off = SPDLOG_LEVEL_OFF, // 关闭所有日志记录。
n_levels
};
2.5 日志等级的使用
- 设置全局日志等级:
可以通过 spdlog::set_level 设置全局日志等级,低于该等级的日志消息将被忽略。
spdlog::set_level(spdlog::level::debug); // 只记录 debug 及以上级别的日志
- 设置单个日志器的日志等级:
可以为每个日志器单独设置日志等级。
auto logger = spdlog::stdout_color_mt("console");
logger->set_level(spdlog::level::info); // 只记录 info 及以上级别的日志
- 记录不同等级的日志:
使用 spdlog 提供的宏或方法记录不同等级的日志。
spdlog::trace("This is a trace message.");
spdlog::debug("This is a debug message.");
spdlog::info("This is an info message.");
spdlog::warn("This is a warning message.");
spdlog::error("This is an error message.");
spdlog::critical("This is a critical message.");
- 检查日志等级:
可以通过 should_log 方法检查某个日志等级是否会被记录。
if (logger->should_log(spdlog::level::info)) {
logger->info("This message will be logged.");
}
2.6 使用 spdlog
以下是一个简单的使用示例:
#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h" // 文件输出
#include "spdlog/sinks/stdout_color_sinks.h" // 控制台输出
int main() {
// 创建一个控制台日志器
auto console_logger = spdlog::stdout_color_mt("console");
console_logger->info("Welcome to spdlog!");
// 创建一个文件日志器
auto file_logger = spdlog::basic_logger_mt("file_logger", "logs/basic-log.txt");
file_logger->info("This message will be written to a file.");
// 设置全局日志级别
spdlog::set_level(spdlog::level::debug);
// 使用格式化日志
spdlog::info("Hello, {}!", "world");
spdlog::warn("This is a warning message.");
spdlog::error("This is an error message.");
// 刷新日志(确保所有日志被写入)
spdlog::shutdown();
return 0;
}
2.7 集成和使用过程中要注意的点
-
日志级别:spdlog 支持多种日志级别(trace, debug, info, warn, error, critical),根据需求设置合适的级别。
-
多线程支持:spdlog 是线程安全的,可以在多线程环境中直接使用。
-
异步日志:如果需要高性能日志记录,可以使用异步日志器(spdlog::async_logger),但需要注意内存占用和刷新策略。
-
日志格式:spdlog 支持自定义日志格式,可以通过 set_pattern 方法设置。
-
性能开销:尽管 spdlog 性能很高,但在高频日志场景中仍需注意性能开销,建议使用异步日志。
-
资源释放:在程序退出前调用 spdlog::shutdown(),确保所有日志被刷新。
3. spdlog 与其他开源日志库的对比
4. spdlog 的优点
-
高性能:专为低延迟和高吞吐量设计。
-
易用性:header-only 设计,集成简单。
-
灵活性:支持多种日志格式、目标和级别。
-
异步日志:适合高性能场景。
-
跨平台:支持 Windows、Linux、macOS 等。
**
5. spdlog 的缺点
-
功能相对简单:相比 Boost.Log 或 log4cxx,功能较少。
-
异步日志的内存占用:在高负载下可能占用较多内存。
-
依赖 C++11:不支持旧版 C++ 标准。
6. 总结
spdlog 是一个非常适合高性能、低延迟场景的日志库,尤其适合需要快速集成和使用的项目。如果需要更复杂的功能(如日志过滤、远程日志等),可以考虑 Boost.Log 或 log4cxx。
参考
【1】spdlog github 仓库
【2】【C++】spdlog光速入门,C++logger最简单最快的库
【3】spdlog日志库说明文档(超详细)
【4】封装 spdlog