C++集成spdlog,spdlog基本使用方法
- 何时输出日志
- 第一步:集成 `spdlog` 到你的项目
- 方法 1:使用包管理器(例如 vcpkg 或 conan)
- 方法 2:手动集成
- 第二步:基本使用
- 第三步:设置日志级别
- 第四步:使用日志文件、将日志输出到文件
- 创建文件日志器
- 设置默认日志器
- 第五步:格式化消息
- 第六步:清理
- 异步日志记录
- 日志旋转
- 自定义格式
- 多个日志目标
- 总结
在软件开发中,日志记录是一个重要的功能,它帮助开发者了解应用程序的运行状态、诊断问题以及监控系统性能。对于算法工程师来说,合理地使用日志同样重要,尤其是在处理复杂的算法或数据处理任务时。以下是一些建议,可以帮助你更好地理解何时以及如何输出相关日志:
何时输出日志
-
错误和异常:当程序遇到错误或异常时,应记录相关信息,包括错误类型、错误消息以及可能的堆栈跟踪。这对于诊断问题至关重要。
-
状态变更:程序状态的重要变更,比如算法流程的开始和结束、关键步骤的完成等,都应该被记录。
-
重要决策:算法在处理数据时做出的重要决策点,例如模型选择、参数调整等,应当记录下来,以便于理解算法的运行过程。
-
性能监控:执行时间较长的操作或关键性能指标,如算法处理速度、内存使用情况等,也应记录,以帮助优化性能。
-
用户操作:如果应用程序与用户交互,用户的关键操作和选择也应被记录。
-
警告:不符合期望但不足以当作错误处理的情况,应以警告的形式记录。比如,使用了默认配置代替缺失的用户输入。
spdlog
是一个高效的 C++ 日志库,提供快速的日志记录功能。它支持多种输出目标,如控制台、文件、循环文件等,并且可以很容易地集成到 C++ 项目中。下面将逐步介绍如何使用 spdlog
。
第一步:集成 spdlog
到你的项目
方法 1:使用包管理器(例如 vcpkg 或 conan)
如果你使用的是像 vcpkg
或 conan
这样的包管理器,你可以通过它们来安装 spdlog
。
-
使用 vcpkg:
vcpkg install spdlog
-
使用 conan:
conan install spdlog/[version]@
方法 2:手动集成
- 从 spdlog GitHub 下载源代码。
- 将
spdlog
目录包含到你的项目中,并在你的编译器中设置包含路径。 - spdlog使用很方便就是将下载下来的包含到自己的include文件夹下就好,注意自己的项目包含目录要添加入include文件夹路径(一般最好为相对路径,类似于./include)
第二步:基本使用
首先,需要包含 spdlog
的头文件:
#include <spdlog/spdlog.h>
然后,你可以创建一个日志器并使用它来记录消息:
#include <spdlog/spdlog.h>
int main() {
// 初始化控制台日志器
spdlog::info("Welcome to spdlog!");
spdlog::error("This is an error message");
spdlog::warn("Warning message");
spdlog::debug("Debug message"); // 默认情况下,debug和trace消息不会显示
return 0;
}
第三步:设置日志级别
spdlog
支持多种日志级别:trace, debug, info, warn, error, critical, off。你可以设置全局日志级别,来控制哪些级别的日志应该被记录。
#include <spdlog/spdlog.h>
int main() {
spdlog::set_level(spdlog::level::info); // 将只记录info及以上级别的日志
spdlog::debug("此条消息不会被显示!");
spdlog::info("此条消息会被显示.");
return 0;
}
第四步:使用日志文件、将日志输出到文件
spdlog
也支持将日志输出到文件:
#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>
int main() {
auto file_logger = spdlog::basic_logger_mt("file_logger", "logs.txt");
spdlog::set_default_logger(file_logger);
spdlog::info("Saved to logs.txt");
return 0;
}
这段代码演示了如何使用 spdlog
将日志信息保存到一个文件中。下面是对各个部分的详细说明:
创建文件日志器
auto file_logger = spdlog::basic_logger_mt("file_logger", "logs.txt");
这行代码创建了一个名为 file_logger
的文件日志器,所有日志消息将被保存到当前目录下的 logs.txt
文件中。spdlog::basic_logger_mt
是一个工厂函数,用于创建并初始化一个多线程安全的文件日志器。
"file_logger"
是日志器的名称,它是一个标识符,可以用来在程序中引用这个特定的日志器。"logs.txt"
指定了日志文件的路径和名称。如果文件不存在,spdlog
会自动创建它。
设置默认日志器
spdlog::set_default_logger(file_logger);
此函数调用将 file_logger
设置为默认日志器。这意味着,当使用不指定日志器名称的 spdlog
日志函数(如 spdlog::info
、spdlog::error
等)时,spdlog
将使用这个 file_logger
来记录日志消息。
第五步:格式化消息
spdlog
支持 Python 风格的消息格式化:
#include <spdlog/spdlog.h>
int main() {
int user_id = 1001;
spdlog::info("User {} logged in", user_id);
return 0;
}
第六步:清理
默认情况下,spdlog
会在程序退出时自动清理所有资源。如果需要,也可以手动调用 spdlog::drop_all()
来清理所有日志器。
这是一个简单的介绍,spdlog
还有很多高级功能,比如日志旋转、异步日志记录、自定义格式等,你可以在 spdlog wiki 上找到更多的信息和高级主题。
spdlog
是一个高性能、灵活的日志记录库,除了基本的日志记录功能之外,它还提供了很多高级功能,比如异步日志记录、日志旋转、自定义格式和多个日志目标。下面讲解一些 spdlog
的进阶使用方法。
异步日志记录
异步日志记录可以显著提高应用程序的性能,因为它将日志消息的格式化和存储操作从主执行线程移到了后台线程。
#include <spdlog/async.h>
#include <spdlog/sinks/basic_file_sink.h>
int main() {
spdlog::init_thread_pool(8192, 1); // 创建异步日志记录的线程池
auto async_file_logger = spdlog::basic_logger_mt<spdlog::async_factory>("async_logger", "async_log.txt");
spdlog::set_default_logger(async_file_logger);
spdlog::info("This is an async log message");
return 0;
}
在这个例子中,我们首先通过 spdlog::init_thread_pool
初始化了一个线程池,然后使用 spdlog::basic_logger_mt<spdlog::async_factory>
创建了一个异步的文件日志器。
日志旋转
日志旋转是一种常见需求,用于控制日志文件的大小和数量,防止日志文件占用过多的磁盘空间。
#include <spdlog/sinks/rotating_file_sink.h>
int main() {
auto rotating_logger = spdlog::rotating_logger_mt("rotating_logger", "rotating_log.txt", 1024 * 1024 * 5, 3);
spdlog::set_default_logger(rotating_logger);
for(int i = 0; i < 10000; ++i) {
spdlog::info("This is a rotating log message {}", i);
}
return 0;
}
这个例子创建了一个名为 rotating_logger
的日志器,它会将日志消息保存到 rotating_log.txt
。日志文件的最大大小被设置为5MB,最多保留3个日志文件。当当前日志文件达到5MB时,spdlog
会自动创建一个新的日志文件,并在有必要时删除最旧的日志文件。
自定义格式
spdlog
允许你自定义日志消息的格式,这通过设置模式字符串来实现。
#include <spdlog/spdlog.h>
int main() {
spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] [thread %t] %v");
spdlog::info("This is a custom formatted log message");
return 0;
}
这个例子中,我们设置了一个新的日志格式,它包括时间戳、日志级别、线程ID和实际的日志消息。
多个日志目标
spdlog
支持同时将日志消息发送到多个目标,比如同时输出到控制台和文件。
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
int main() {
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("multi_sink_log.txt");
spdlog::logger multi_sink_logger("multi_sink", {console_sink, file_sink});
multi_sink_logger.set_level(spdlog::level::info);
multi_sink_logger.info("This log message goes to both console and file");
return 0;
}
在这个例子中,我们创建了两个日志汇(sink):一个用于控制台输出,另一个用于文件输出。然后,我们创建了一个 spdlog::logger
对象,同时传入了这两个汇。这样,所有通过这个日志器记录的消息都会同时出现在控制台和文件中。
总结
spdlog
提供的这些高级功能使其成为一个非常强大和灵活的日志库,适用于各种不同的日志记录需求。通过利用这些高级功能,你可以更好地控制日志记录的行为,优化应用程序的性能,以及改善日志的可读性和可管理性。