spdlog日志库的封装使用

spdlog日志库的封装使用spdlog 日志库的封装使用

前言

编码过程中,日志是必要的一个组件,我们选择使用哪个日志库呢?

参考:15 best C++ Logging libraries in 2022

C++ 日志库用于在用 C++ 编写的应用程序中记录信息。日志记录可以在不同的粒度级别、不同的日志类型和不同的输出目标上完成。一个好的日志库是任何应用程序的关键组件。它允许您执行各种调试任务,例如跟踪错误、监控性能甚至跟踪用户操作。日志记录是一种跟踪程序正在做什么的方法。在收集统计数据、分析性能问题,甚至只是为了大致了解应用程序内部发生的情况时,日志也很有用。有几个流行的 C++ Logging 开源库可供开发人员使用: spdlog – 快速 C 日志记录库;glog – Google 日志模块的 C 实现;easyloggingpp – 单头 C 日志库。

随大流,选择使用人数多,商业友好的spdlog


spdlog的基本使用

见官方文档:spdlog在这里插入图片描述


spdlog日志库的封装

在一个多人合作的项目中,日志库封装的越顺手,程序员在代码中越多的使用日志语句,给后续的分析bug带来便利。

第一种封装方式,是只封装一个日志库。好处是封装起来较为容易,从而封装的效果也比较好;坏处是不便于替换使用其他日志库。

第二种封装方式,以相同的接口,同时封装多种日志库,在编译的时候,使用编译选项决定使用哪种日志库。好处是可以替换使用日志库。缺点是增大了封装的难度,在程序员水平一定的时候,封装的效果不大好。

spdlog直接拿过来不太好用。比如,我想在一个进程的任何地方,都可以使用同一个logger。这是一个比较合理的要求,只用初始化一次,只输出到一个日志文件。我们可以在main中初始化一日志,在进程的其他地方,使用 spdlog::get线程安全的访问记录器。这样做的缺点是,使用日志库的所有程序员都需要知道spdlog库api的使用方式。

所以,我们需要对日志库进行封装,屏蔽掉细节,以保证日志库被方便安全的被使用

在封装的时候,我在考虑要不要将其封装成单例模式。在整个进程中使用同一个logger,似乎是可以封装成单例模式,或者全局变量?。但是如果此时,在一个进程中,希望可以有两个或者多个功能的logger,则不应该使用单例模式。

最后,我选择使用单例模式。因为,如果有在一个进程中使用多种logger,那似乎可以将程序分为多进程。

因日志库,而不得不拆分程序为多进程,似乎是不应该的。先写成单例模式吧,日志有需要再修改。

boost1.46曾有过Singleton的类模板,本打算借鉴借鉴,但这个类被移除了。参考下面两个链接,使用static来实现单例。(文中讨论的单例模式的缺点,没看懂,懵~)

  • Modern C++ Singleton Template
  • What are drawbacks or disadvantages of singleton pattern

下面是对日志库的封装。这个封装的使用,可参考da1234cao/FreeFile:

#pragma once // 参考1:https://blog.csdn.net/gongjianbo1992/article/details/ // 参考2:https://techartlife.com/%E8%AE%A1%E7%AE%97%E6%9C%BA/%E7%BC%96%E7%A8%8B/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/cpp/%E5%B0%81%E8%A3%85spdlog%E5%BA%93/ // 参考3:https://github.com/SergiusTheBest/plog/blob/master/include/plog/Log.h #include "exception.hpp" #include 
    
      #include 
     
       #include 
      
        #include 
       
         #include 
        
          namespace Log { struct log_execption : virtual base_exception {}; class SPDLOG { private: SPDLOG() = default; private: std::shared_ptr 
         
           logger_ptr_; void setLogLevel(const std::string& level); public: static SPDLOG& getInstance() { static SPDLOG instance; return instance; } // 初始化一个默认日志文件logger: 日志路径;logger name; 日志等级;单个日志文件最大大小;回滚日志文件个数;日志是否线程安全; void init(std::string log_file_path,std::string logger_name, std::string level, size_t max_file_size, size_t max_files, bool mt_security = false); std::shared_ptr 
          
            logger() { return logger_ptr_; } }; // SPDLOG class #define LOG_TRACE(...) SPDLOG::getInstance().logger().get()->trace(__VA_ARGS__) #define LOG_DEBUG(...) SPDLOG::getInstance().logger().get()->debug(__VA_ARGS__) #define LOG_INFO(...) SPDLOG::getInstance().logger().get()->info(__VA_ARGS__) #define LOG_WARN(...) SPDLOG::getInstance().logger().get()->warn(__VA_ARGS__) #define LOG_ERROR(...) SPDLOG::getInstance().logger().get()->error(__VA_ARGS__) #define LOG_CRITICAL(...) SPDLOG::getInstance().logger().get()->critical(__VA_ARGS__) } // Log namespace void Log::SPDLOG::init(std::string log_file_path, std::string logger_name, std::string level, size_t max_file_size, size_t max_files, bool mt_security) { try { if (mt_security) { logger_ptr_ = spdlog::rotating_logger_mt(logger_name, log_file_path, max_file_size, max_files); } else { logger_ptr_ = spdlog::rotating_logger_st(logger_name, log_file_path, max_file_size, max_files); } setLogLevel(level); logger_ptr_->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] [%t] [%s %!:%#] %v"); //设置格式:https://spdlog.docsforge.com/v1.x/3.custom-formatting/ } catch (const spdlog::spdlog_ex& ex) { BOOST_THROW_EXCEPTION(log_execption() << err_str("Log initialization failed: " + std::string(ex.what())) ); } } void Log::SPDLOG::setLogLevel(const std::string &level) { char L = toupper(level[0]); if (L == 'T') { // trace logger_ptr_->set_level(spdlog::level::trace); logger_ptr_->flush_on(spdlog::level::trace); } else if (L == 'D') { // debug logger_ptr_->set_level(spdlog::level::debug); logger_ptr_->flush_on(spdlog::level::debug); } else if (L == 'I') { // info logger_ptr_->set_level(spdlog::level::info); logger_ptr_->flush_on(spdlog::level::info); } else if (L == 'W') { // warn logger_ptr_->set_level(spdlog::level::warn); logger_ptr_->flush_on(spdlog::level::warn); } else if (L == 'E') { // error logger_ptr_->set_level(spdlog::level::err); logger_ptr_->flush_on(spdlog::level::err); } else if (L == 'C') { // critical logger_ptr_->set_level(spdlog::level::critical); logger_ptr_->flush_on(spdlog::level::critical); } else { BOOST_THROW_EXCEPTION(log_execption() << err_str("level set error " + level) ); } } 
           
          
         
        
       
      
    
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/221309.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午6:25
下一篇 2026年3月17日 下午6:26


相关推荐

  • 重度Cursor用户 最强 Cursor Rules 和 Cursor 配置 mcp 以及最佳实践配置方式

    重度Cursor用户 最强 Cursor Rules 和 Cursor 配置 mcp 以及最佳实践配置方式

    2026年3月16日
    2
  • Pytest(13)命令行参数–tb的使用「建议收藏」

    Pytest(13)命令行参数–tb的使用「建议收藏」前言pytest使用命令行执行用例的时候,有些用例执行失败的时候,屏幕上会出现一大堆的报错内容,不方便快速查看是哪些用例失败。–tb=style参数可以设置报错的时候回溯打印内容,可以设置参

    2022年7月28日
    8
  • python omron Fins -PLC和上位机socket通讯( tcy)

    python omron Fins -PLC和上位机socket通讯( tcy)1 说明 目前测试支持 CP NJ 系列 PLC 其他待验证 差别主要在于 PLC 数据地址的分配 1 文档说明 fins 命令格式 2 实例 pyqt5 python socket thread 本程序通过 pyqt5 制作画面 控制 omronNJplc 的启停及报警信息显示 参数设置 上位机发送 FINSTCP 命令读写 NJ 数据 1 参数说明 NJ301 的 IP 地址 10 110 59

    2026年3月16日
    4
  • spring starter(怎么编写自己的starter)

    微服务架构从本质上说其实就是分布式架构,与其说是一种新架构,不如说是一种微服务架构风格。简单来说,微服务架构风格是要开发一种由多个小服务组成的应用。每个服务运行于独立的进程,并且采用轻量级交互。多数情况下是一个HTTP的资源API。这些服务具备独立业务能力并可以通过自动化部署方式独立部署。这种风格使最小化集中管理,从而可以使用多种不同的编程语言和数据存储技术。对于微服务架构系统,由于其服务粒度…

    2022年4月10日
    62
  • HSRP详解

    HSRP详解HSRP 功能及配置 思科 为了实现网络出口一方出现故障 网络能够自动切换到正常线路进行通信 不影响客户机上网 HSRP vrrp HSRP 私有标准 思科设备上才能配置这个 VRRP 公有标准 Hsrp 和 vrrp 都是做硬件设备的备份 规划网段 2 基础配置 Switch0 接入层 enableconftv

    2026年3月19日
    2
  • 苹果电脑navicat premium激活码-激活码分享[通俗易懂]

    (苹果电脑navicat premium激活码)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

    2022年3月28日
    466

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号