Spdlog日志库

蒸汽
蒸汽
发布于 2024-12-17 / 5 阅读
0
0

Spdlog日志库

🚒 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 用于管理这些组件。

image.png

🏎️3.文件IO

image.png

🚑4. spdlog使用

image.png

#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;  
}


评论