🚒 1.日志作用
日志在软件开发和维护中扮演着至关重要的角色。它不仅帮助开发者追踪程序运行状态,还能在出现问题时提供宝贵的调试信息。通过日志,我们能够了解软件在特定时间点的行为,分析性能瓶颈,甚至预测潜在的系统故障。日志的重要性不言而喻,它就像是软件世界中的“黑匣子”,记录着程序的每一个细微动作。
🚌2.Spdlog
2.1spdlog介绍
spdlog 是一款高效的C++日志库,它以其极高的性能和零成本的抽象而著称。spdlog 支持异步和同步日志记录,提供多种日志级别,并允许用户将日志输出到控制台、文件或自定义的接收器。
# 项目下载
git clone https://github.com/gabime/spdlog.git
#编译
cd spdlog
mkdir build
cd build
cmake ..
make -j
#安装
sudo make install
2.2 spdlog 为何高效
spdlog 的设计哲学是尽量减少日志记录的开销,即使在高负载的情况下也能保持高性能。它通过以下几种方式实现这一点:
0成本抽象:spdlog通过模板和内联函数来实现零成本抽象, 确保只有在真正需要时才进行日志记录。
异步日志记录:spdlog 支持异步日志记录,这意味着它可以将日志消息发送到线程池进行处理,从而减少对主线程性能的影响。
高效地格式化:spdlog使用fmt 库进行高效的字符串格式化, 减少了格式化日志消息所需的时间。
2.3 spdlog特征
spdlog 的性能特点使其在高性能应用中非常受欢迎:
极高的日志记录速度:spdlog 能够在每秒记录数百万条日志消息,这对于需要处理大量日志数据的应用来说是非常重要的。
低内存占用:spdlog的设计确保了即使在高负载下,它也能保持低内存占用。
灵活的配置:用户可以根据需要配置spdlog,选择异步或同步日志记录,以及选择不同的日志级别和输出目标。
2.4 spdlog输出控制
spdlog 提供了丰富的输出控制选项,允许用户根据需要定制日志输出:
多种日志级别:spdlog 支持多种日志级别,包括trace、 debug、info、warn、error 和 critical,用户可以根据需要选择合适的日志级别。
多种输出目标:用户可以将日志输出到控制台、文件或通过网络发送到远程服务器。
格式化输出:spdlog 支持格式化输出,允许用户以结构化的方式输出日志消息。
2.5 spdlog 处理流程
Spdlog的流程非常简单,但是每个组件都扮演着重要的角色。 Loggers 负责记录日志消息,Sinks 决定了日志消息的输出位置,Formatters 负责将日志消息转换为特定格式,Async Logger 异步地将日志消息写入到目标 Sink 中,Registry 用于管理这些组件。
🏎️3.文件IO
🚑4. spdlog使用
#include <chrono>
#include <memory>
#include <spdlog/async.h>
#include <spdlog/async_logger.h>
#include <spdlog/common.h>
#include <spdlog/logger.h>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
class my_formatter_flag : public spdlog::custom_flag_formatter
{
public:
void format(const spdlog::details::log_msg &, const std::tm &, spdlog::memory_buf_t &dest) override
{
std::string some_txt = "mark-flag";
dest.append(some_txt.data(), some_txt.data() + some_txt.size());
}
std::unique_ptr<custom_flag_formatter> clone() const override
{
return spdlog::details::make_unique<my_formatter_flag>();
}
};
int main() {
spdlog::info("hello world");
auto logger = spdlog::stdout_color_mt<spdlog::async_factory>("console");
logger->info("hello world too!!");
spdlog::get("console")->info("hello world too too !!!");
auto sink1 = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
auto sink2 = std::make_shared<spdlog::sinks::basic_file_sink_mt>("mark.txt");
auto formatter = std::make_unique<spdlog::pattern_formatter>();
formatter->add_flag<my_formatter_flag>('*').set_pattern("[%n] [%*] [%^%l%$] %v");
sink1->set_formatter(std::move(formatter));
sink2->set_pattern("[%^%l%$] %v");
auto logger1 = std::make_shared<spdlog::logger>(std::string("console1"));
logger1->sinks().push_back(sink1);
logger1->sinks().push_back(sink2);
spdlog::register_logger(logger1);
spdlog::get("console1")->info("hello world too too too!!!!");
SPDLOG_INFO("hello mark too!");
SPDLOG_LOGGER_INFO(spdlog::get("console1"), "hello mark too too !!!");
auto logger_mark = spdlog::create_async<spdlog::sinks::basic_file_sink_mt>("mark", "mark1.txt");
logger_mark->info("hello logger_mark");
spdlog::init_thread_pool(8292, 8);
std::vector<spdlog::sink_ptr> sinks;
sinks.push_back(sink1);
sinks.push_back(sink2);
auto logger_tp = std::make_shared<spdlog::async_logger>("tp", sinks.begin(), sinks.end(), spdlog::thread_pool(), spdlog::async_overflow_policy::overrun_oldest);
logger_tp->info("hello thread pool");
logger_tp->flush();
logger_tp->flush_on(spdlog::level::err);
spdlog::flush_every(std::chrono::seconds(5));
return 0;
}