Spdlog日志库的使用,支持文件名/行号/函数名的log打印输出-阿里云开发者社区

开发者社区> y2hr4cjzssnlm> 正文

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

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





版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云云效功能升级,支持快速创建多个应用的独立测试环境
作为测试人员来说,搭建测试环境是测试实施的一个重要阶段,测试环境适合与否会严重影响测试结果的真实性和正确性。为了更好地服务用户,近日,阿里云研发协同平台-云效宣布功能升级,支持快速创建多个应用的独立测试环境,对于企业开发人员和测试人员来说,又是一大福音。
4512 0
js同域名下不同文件下使用coookie
//写cookies function setCookie(name,value) { var Days = 30; var exp = new Date(); exp.
575 0
SQL SERVER数据库删除LOG文件和清空日志的方案
原文:SQL SERVER数据库删除LOG文件和清空日志的方案 数据库在使用过程中会使日志文件不断增加,使得数据库的性能下降,并且占用大量的磁盘空间。SQL Server数据库都有log文件,log文件记录用户对数据库修改的操作。
4416 0
log4j配置单独日志文件输出
log4j.logger.batteryHistory=ERROR,BD log4j.appender.BD=org.apache.log4j.FileAppender log4j.appender.
870 0
682
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载