c++ 日志输出库 spdlog 简介(2)

继续上一篇,example.cpp解析。

1、set_pattern 自定义日志格式

官方参考:https://github.com/gabime/spdlog/wiki/3.-Custom-formatting

可以为所有的log制定格式,也可以为指定的log制定格式,注意下面代码中rotating_logger为指针变量。

auto rotating_logger = spd::rotating_logger_mt("some_logger_name", "logs/rotating.txt", 256, 2);
// Customize msg format for all messages
        spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***");
        rotating_logger->info("This is another message with custom format");
        //Customize msg format for a specific logger object:
        rotating_logger->set_pattern("[%H:%M:%S %f] [thread %t] %v ***");

详细的格式说明在github上有,在此截图如下:

2、set_level 设置日志级别

低于设置级别的日志将不会被输出。各level排序,数值越大级别越高:

// Runtime log levels
        spd::set_level(spd::level::info); //Set global log level to info
        console->debug("This message should not be displayed!");
        console->set_level(spd::level::debug); // Set specific logger‘s log level
        console->debug("This message should be displayed..");

第一行日志debug级别低于设定的级别info,在level为info时不会被输出。

第二行日志debug级别与设定的级别相同,所以可以显示出来。

typedef enum
{
    trace = 0,
    debug = 1,
    info = 2,
    warn = 3,
    err = 4,
    critical = 5,
    off = 6
} level_enum;

3、编译阶段修改日志输出级别 SPDLOG_TRACE 和 SPDLOG_DEBUG

官方参考:https://github.com/gabime/spdlog/wiki/8.-Tweaking

当定义了宏定义 SPDLOG_TRACE_ON 时,可以用SPDLOG_TRACE语句输出trace级别的log,SPDLOG_DEBUG_ON也是同理。

#define SPDLOG_TRACE_ON
#define SPDLOG_DEBUG_ON
// Compile time log levels
        // define SPDLOG_DEBUG_ON or SPDLOG_TRACE_ON
        SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23);
        SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23);

需要注意的是,如果不使用set_level命令设置log的输出级别,默认级别就是info级别,此时即使定义了这两个宏,debug和trace信息也不会输出。所以使用时需要先用set_level把级别设为trace才可以。

console->set_level(spd::level::trace); // Set specific logger‘s log level
        // Compile time log levels
        // define SPDLOG_DEBUG_ON or SPDLOG_TRACE_ON
        SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23);
        SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23);

以下是输出结果:

注意trace和debug的输出不太一样,打开spdlog.h,查看SPDLOG_TRACE的定义,可以发现trace中还输出了文件的位置(“__FILE__”)。

#ifdef SPDLOG_TRACE_ON
#  define SPDLOG_STR_H(x) #x
#  define SPDLOG_STR_HELPER(x) SPDLOG_STR_H(x)
#  ifdef _MSC_VER
#    define SPDLOG_TRACE(logger, ...) logger->trace("[ " __FILE__ "(" SPDLOG_STR_HELPER(__LINE__) ") ] " __VA_ARGS__)
#  else
#    define SPDLOG_TRACE(logger, ...) logger->trace("[ " __FILE__ ":" SPDLOG_STR_HELPER(__LINE__) " ] " __VA_ARGS__)
#  endif
#else
#  define SPDLOG_TRACE(logger, ...) (void)0
#endif

#ifdef SPDLOG_DEBUG_ON
#  define SPDLOG_DEBUG(logger, ...) logger->debug(__VA_ARGS__)
#else
#  define SPDLOG_DEBUG(logger, ...) (void)0
#endif

4、同步和异步设置  Asynchronous logging

官方说明:https://github.com/gabime/spdlog/wiki/6.-Asynchronous-logging

默认情况下是不开启异步模式的,开启异步模式方式如下:

size_t q_size = 4096; //queue size must be power of 2
    spdlog::set_async_mode(q_size);

队列大小:

队列占用的内存 = 设置的队列大小 * slot的大小, 64位系统下slot大小为104字节。由此可根据系统的log输出总量来确定队列大小。

队列机制:

异步模式下,所有输出的日志将先存入队列,再由工作者线程从队列中取出日志并输出。当队列存满时,需要根据设置好的队列存满策略来处置新来的日志(阻塞消息或者丢弃消息)。如果工作者线程中抛出了异常,向队列写入下一条日志时异常会再次抛出,可以在写入队列时捕捉工作者线程的异常。

队列存满时(Full queue policy)两种应对方式:

(1)阻塞新来的日志,直到队列中有剩余空间。这是默认的处理方式。

(2)丢弃新来的日志。如下:

spdlog::set_async_mode(q_size, spdlog::async_overflow_policy::discard_log_msg)

两种应对方式如下:

// Async overflow policy - block by default.
//
enum class async_overflow_policy
{
    block_retry, // Block / yield / sleep until message can be enqueued
    discard_log_msg // Discard the message it enqueue fails
};

5、处理spdlog的异常  set_error_handler

官方说明:https://github.com/gabime/spdlog/wiki/Error-handling

当输出日志时发生异常时,spdlog会向std::err 打印一条语句,为了避免输出的异常语句刷屏,打印频率被限制在每分钟一条。

下面函数执行时,由于最后一条输出log的语句中四个参数只给了一个,所以spdlog调用了异常处理函数,输出异常。

void err_handler_example()
{
    //can be set globaly or per logger(logger->set_error_handler(..))
    spdlog::set_error_handler([](const std::string& msg)
    {
        std::cerr << "my err handler: " << msg << std::endl;
    });
    spd::get("console")->info("some invalid message to trigger an error {}{}{}{}", 3);
}

6、apply_all 使所有的logger同时输出

所有注册过的logger都会输出End of example 这句话,代表程序结束。

// Apply a function on all registered loggers
        spd::apply_all([&](std::shared_ptr<spdlog::logger> l)
        {
            l->info("End of example.");
        });

7、drop -- 释放logger

在程序结束时,应该调用drop_all() 释放所有logger。

There is a bug in VS runtime that cause the application dead lock when it exits. If you use async logging, please make sure to call spdlog::drop_all() before main() exit. If some loggers are not in the registry, those should be released manually as well. stackoverflow: std::thread join hangs if called after main exits when using vs2012 rc

// Release and close all loggers
        spdlog::drop_all();

或者单独drop某个logger

spd::drop("console");
        spd::drop("basic_logger");

原文地址:https://www.cnblogs.com/oucsheep/p/8433918.html

时间: 2024-10-15 21:52:56

c++ 日志输出库 spdlog 简介(2)的相关文章

c++ 日志输出库 spdlog 简介(1)

参考文章: log库spdlog简介及使用 - 网络资源是无限的 - CSDN博客 http://blog.csdn.net/fengbingchun/article/details/78347105 spdLog的使用 - 烟消bug云散的专栏 - CSDN博客 http://blog.csdn.net/yanxiaobugyunsan/article/details/79088533 官方参考文档: QuickStart · gabime/spdlog Wiki · GitHub https

9 个技巧,解决 K8s 中的日志输出问题

作者 | 元乙??阿里云存储服务技术专家 导读:近年来,越来越多的同学咨询如何为 Kubernetes 构建一个日志系统,或者是来求助在此过程中遇到一系列问题如何解决,授人以鱼不如授人以渔,于是作者想把这些年积累的经验以文章的形式发出来,让看到文章的同学少走弯路.K8s 日志系列文章内容偏向落地实操以及经验分享,且内容会随着技术的迭代而不定期更新,本文为该系列文章的第 3 篇. 第一篇:<6 个 K8s 日志系统建设中的典型问题,你遇到过几个?> 第二篇:<一文看懂 K8s 日志系统设计

如何快速的把日志输出到磁盘上

不管是做客户端业务,还是做服务端业务,日志子系统都是非常重要的一个组件. 日志系统的输出目的地可以是disk,也可以是tty,更可以是network. 我的日志系统可以输出到tty,不同log level可以有不同的color,这样看日志非常的醒目,当然这里着重谈的是如何快速的把log内容写到磁盘上. 其实,如何快速的把log内容写到磁盘上,网上文章已经汗牛充栋,真正高质量的没多少,本篇可能也是狗尾续貂之作.不过,我的log子系统能够达到106M/s的输出速率. 详细介绍我的log系统之前,推荐

日志输出法则

运行日志应用场景 原型迭代过程 该场景下,一定需要日志输出.原因很显然,因为是个迭代过程,整体结构模型并不明确,一些逻辑都不是很可靠的,故需要提供一个侧面可供观察程序运行动态. 二次开发 二次开发一般也是采用一种原型来迭代完成的.即便不是基于原型迭代变化,那日志观察则更是需要,至少依赖平台的一些调用我们需要观察.程序员一般对于不是自己定义的逻辑都是不能完全信任的.除非有可靠评测数据. 对于有单元测试的依赖项 有单元测试,那就是说有可信可靠的评测数据.对于这部分依赖项,同二次开发说明的,那我们只管

ACE服务端编程5:ACE日志输出和跟踪

服务器程序经常需要在命令行中显示错误消息.状态或者用来跟踪程序的执行路径,最简单的方法是使用printf. ACE提供了更强大日志设施: 1.可以在编译时启用或禁用宏: 2.可以动态的启用或禁用宏: 3.支持日志严重级别: 4.支持日志重定向: 5.支持多线程安全和线程级配置: 使用ACE的日志相关功能,需要引入<ace/Log_Msg.h>头文件. ACE日志输出 ACE提供了两个宏来支持日志输出:ACE_DEBUG.ACE_ERROR. 这两个宏的内部实现和行为都是一样,只是为了在语义上区

支持windows linux下将指定内存段转为16进制与ascii码的日志输出类

来源:http://blog.csdn.net/lezhiyong 1. 简介 将指定内存段转为16进制与asci码的输出到日志文件的类. 2. 功能介绍 1) 支持window与linus双系统. 2) 可指定输出目录. 3) 日志能输出的时间精确到毫秒,日志能输出线程号. 4) 提供字符串输出. 5) 提供指定内存转换为16进制输出. 6) 提供指定内存转换为16进制和ascii码同时输出. 7) 可调整16进制输出间距. 3. 原理和算法 1) 模块是基于C++语言编写: 2) 通过条件定

【原创】日志输出到串口设备导致的问题

问题场景: 测试人员报告,业务 modb 作为 RabbitMQ 的消费者,消费消息的速度非常慢,慢到大约每秒 2 条左右,从而导致 RabbitMQ 的队列中积压了 4000+ 条消息. 排查过程: 先通过 top 命令定位一下 [[email protected]_1 ~]# top -Hp 8177 top - 09:50:33 up 34 min, 8 users, load average: 4.76, 4.32, 3.65 Tasks: 2 total, 0 running, 2 s

Python3.x:日期库dateutil简介

Python3.x:日期库dateutil简介 安装 pip install python-dateutil 关于parser #字符串可以很随意,可以用时间日期的英文单词,可以用横线.逗号.空格等做分隔符. #没指定时间默认是0点,没指定日期默认是今天,没指定年份默认是今年. from dateutil.parser import parse parse("Wed, Nov 12") #输出结果:datetime.datetime(2013, 11, 12, 0, 0) parse(

Snort日志输出插件详解

Snort是一款老牌的开源入侵检测工具,本文主要讨论他作为日志分析时的各种插件的应用.Snort的日志一般位于:/var/log/snort/目录下.可以通过修改配置文件来设置Snort的报警形式.基于文本的格式.Libpcap格式和数据库是Snort最重要的三种报警形式.本文主要对每种报警形式及其配置进行介绍. 1工作模式及输出插件 Snort拥有3种工作模式,分别为嗅探器模式.分组日志模式与网络入侵检测模式. (1)嗅探器模式 Snort使用Libpcap包捕获库,即TCPDUMP使用的库.