Spdlog日志库的使用,支持文件名/行号/函数名的log打印输出

本文涉及的产品
文本翻译,文本翻译 100万字符
图片翻译,图片翻译 100张
日志服务 SLS,月写入数据量 50GB 1个月
简介: Spdlog日志库的使用,支持文件名/行号/函数名的log打印输出

一、简介


spdlog是基于C++ 11的日志组件,它非常轻量,使用时你仅仅需要引入头文件就可以了。


https://github.com/gabime/spdlog


https://github.com/gabime/spdlog/wiki/3.-Custom-formatting



二、线程安全


命名空间 spdlog:: 下面的大多数方法是线程安全的。已知以下三个是线程不安全的,使用时请注意:


void spdlog::set_pattern(const std::string&);


void spdlog::set_formatter(formatter_ptr);


void spdlog::set_error_handler(log_err_handler);


日志对象的大部分方法也是线程安全的,除了以下三个:


void spdlog::logger::set_pattern(const std::string&);

void spdlog::logger::set_formatter(formatter_ptr);

void spdlog::set_error_handler(log_err_handler);


三、使用示例


函数名带后缀_mt的意思是multi thread(速度稍微慢一点点,考虑了多线程并发),_st的意思是single thread(速度较块)。所有以_mt结尾的SINK都是线程安全的,以_st结尾的则不是。

#include "spdlog/spdlog.h"
#include <iostream>
// 多线程的基于控制台(stdout)的日志记录器,支持高亮。类似的stdout_color_st是单线程版本
auto console = spdlog::stdout_color_mt( "console" );
// 基于文件的简单日志
auto logger = spdlog::basic_logger_mt("basic_logger", "logs/basic.txt");
// 基于滚动文件的日志,每个文件5MB,三个文件
auto logger = spdlog::rotating_logger_mt("file_logger", "myfilename", 1024 * 1024 * 5, 3);
// 定制输出格式
spdlog::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***");
// 多个日志器共享SINK
auto daily_sink = std::make_shared<spdlog::sinks::daily_file_sink_mt>("logfile", 23, 59);
// 下面几个同步日志器共享的输出到目标文件
auto net_logger = std::make_shared<spdlog::logger>("net", daily_sink);
auto hw_logger = std::make_shared<spdlog::logger>("hw", daily_sink);
auto db_logger = std::make_shared<spdlog::logger>("db", daily_sink); 
// 一个日志器使用多个SINK
std::vector<spdlog::sink_ptr> sinks;
sinks.push_back( std::make_shared<spdlog::sinks::stdout_sink_st>());
sinks.push_back( std::make_shared<spdlog::sinks::daily_file_sink_st>( "logfile", 23, 59 ));
auto combined_logger = std::make_shared<spdlog::logger>( "name", begin( sinks ), end( sinks ));
spdlog::register_logger( combined_logger );
// 异步
// 每个日志器分配8192长度的队列,队列长度必须2的幂
spdlog::set_async_mode(8192); 
// 程序退出前清理
spdlog::drop_all();
// 注册日志器
spdlog::register_logger(net_logger);
// 注册后,其它代码可以根据名称获得日志器
auto logger = spdlog::get(net_logger);
// 记录日志
// 设置最低级别
console->set_level(spdlog::level::debug);
console->debug("Hello World") ;
// 使用占位符
console->info("Hello {}" ,"World"); 
// 带格式化的占位符:d整数,x十六进制,o八进制,b二进制                
console->warn("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
// 带格式化的占位符:f浮点数
console->info("Support for floats {:03.2f}", 1.23456);
// 左对齐,保证30字符宽度
console->error("{:<30}", "left aligned");
// 指定占位符位置序号
console->info("Positional args are {1} {0}..", "too", "supported");
// 记录自定义类型,需要重载<<操作符
#include <spdlog/fmt/ostr.h> 
class Duck{}
std::ostream& operator<<(std::ostream& os, const Duck& duck){ 
    return os << duck.getName(); 
}
Duck duck;
console->info("custom class with operator<<: {}..", duck);

四、我个人的使用示例

#define SPDLOG_NAME         "SmartDispenser"
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE//必须定义这个宏,才能输出文件名和行号
#include <spdlog/spdlog.h>
#include <spdlog/sinks/rotating_file_sink.h>
bool CInitSoft::initLog(void)
{
  //初始化日志spdlog,https://github.com/gabime/spdlog
  CString strFilePath = FILEMANAGE->GetLogsDir() + _T("\\logApp.txt");
  std::string logpath = CT2A(strFilePath.GetBuffer());
  strFilePath.ReleaseBuffer();
  try
  {
    auto rotating_logger = spdlog::rotating_logger_mt(SPDLOG_NAME, logpath, 1024 * 1024 * 1, 3);
    spdlog::set_default_logger(rotating_logger);
    rotating_logger->set_level(spdlog::level::debug);
    //输出格式请参考https://github.com/gabime/spdlog/wiki/3.-Custom-formatting
    rotating_logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e][thread %t][%@,%!][%l] : %v");
#if _DEBUG
    rotating_logger->debug("test1");//不会输出文件名和行号
    spdlog::get(SPDLOG_NAME)->info("test2");//
    SPDLOG_LOGGER_DEBUG(rotating_logger, "test3 {}", 3);//会输出文件名和行号
    int a = 4;
    SPDLOG_LOGGER_DEBUG(rotating_logger, "test4 {}", a);
    SPDLOG_DEBUG("test5");
#endif
  }
  catch (const spdlog::spdlog_ex& ex)
  {
    std::cout << "Log initialization failed: " << ex.what() << std::endl;
    CString info;
    info.Format(_T("log init failed: %s\n"), ex.what());
    addInitInfo(theApp.MyMsgString(_T("日志初始化失败!"), info));
    return false;
  }
  return true;
}

请重点关注:


#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE//必须定义这个宏,才能输出文件名和行号


SPDLOG_LOGGER_DEBUG(rotating_logger, "test3 {}", 3);//会输出文件名和行号



五、姊妹篇


Qt日志重定向qInstallMessageHandler,输出至文件及网络


Qt日志库Log4Qt的使用,支持文件名/行号/函数名的打印输出





相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
2天前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
64 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
28天前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
176 3
|
26天前
|
PyTorch 算法框架/工具
Pytorch学习笔记(七):F.softmax()和F.log_softmax函数详解
本文介绍了PyTorch中的F.softmax()和F.log_softmax()函数的语法、参数和使用示例,解释了它们在进行归一化处理时的作用和区别。
271 1
Pytorch学习笔记(七):F.softmax()和F.log_softmax函数详解
|
29天前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1607 14
|
24天前
|
Python
log日志学习
【10月更文挑战第9天】 python处理log打印模块log的使用和介绍
25 0
|
26天前
|
数据可视化
Tensorboard可视化学习笔记(一):如何可视化通过网页查看log日志
关于如何使用TensorBoard进行数据可视化的教程,包括TensorBoard的安装、配置环境变量、将数据写入TensorBoard、启动TensorBoard以及如何通过网页查看日志文件。
142 0
|
29天前
|
存储 分布式计算 NoSQL
大数据-136 - ClickHouse 集群 表引擎详解1 - 日志、Log、Memory、Merge
大数据-136 - ClickHouse 集群 表引擎详解1 - 日志、Log、Memory、Merge
35 0
|
29天前
|
缓存 Linux 编译器
【C++】CentOS环境搭建-安装log4cplus日志组件包及报错解决方案
通过上述步骤,您应该能够在CentOS环境中成功安装并使用log4cplus日志组件。面对任何安装或使用过程中出现的问题,仔细检查错误信息,对照提供的解决方案进行调整,通常都能找到合适的解决之道。log4cplus的强大功能将为您的项目提供灵活、高效的日志管理方案,助力软件开发与维护。
49 0
|
2月前
|
Java
日志框架log4j打印异常堆栈信息携带traceId,方便接口异常排查
日常项目运行日志,异常栈打印是不带traceId,导致排查问题查找异常栈很麻烦。
|
2月前
|
存储 运维 监控
超级好用的C++实用库之日志类
超级好用的C++实用库之日志类
36 0