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

     
  • 相关阅读:
    Class.forName()用法详解 【转】
    Java ——代理模式[转发]
    Java堆和栈的区别
    CSS中文字体的英文名称(simsun)宋体,(Microsoft YaHei)微软雅黑
    学了一个封装的jquery插件,感觉还成
    视差滚动(Parallax Scrolling)效果的原理和实现
    解决jQuery中dbclick事件触发两次click事件
    jquery之stop()的用法
    创意 idea
    软件开发方法的综述
  • 原文地址:https://www.cnblogs.com/lidabo/p/16643830.html
Copyright © 2020-2023  润新知