DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  4737 随笔 :: 2 文章 :: 542 评论 :: 1615万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

一、简介

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的使用,支持文件名/行号/函数名的打印输出

 

 
posted on   DoubleLi  阅读(7280)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2021-08-31 DNS服务器搭建与配置
2021-08-31 DNS服务原理与搭建自己的DNS服务器
2021-08-31 浅析DNS域名解析过程
2017-08-31 windows环境下 生成git公钥和私钥
2017-08-31 TortoiseGit创建本地库并提交到远程服务器
2015-08-31 在Linux运行期间升级Linux系统(Uboot+kernel+Rootfs)
2015-08-31 【详解】嵌入式开发中固件的烧录方式
点击右上角即可分享
微信分享提示