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

1、set_pattern 自定义日志格式

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

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

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

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

2、set_level 设置日志级别

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

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

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

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

  1. typedef enum
  2. {
  3. trace = ,
  4. debug = ,
  5. info = ,
  6. warn = ,
  7. err = ,
  8. critical = ,
  9. off =
  10. } 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也是同理。

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

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

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

以下是输出结果:

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

  1. #ifdef SPDLOG_TRACE_ON
  2. # define SPDLOG_STR_H(x) #x
  3. # define SPDLOG_STR_HELPER(x) SPDLOG_STR_H(x)
  4. # ifdef _MSC_VER
  5. # define SPDLOG_TRACE(logger, ...) logger->trace("[ " __FILE__ "(" SPDLOG_STR_HELPER(__LINE__) ") ] " __VA_ARGS__)
  6. # else
  7. # define SPDLOG_TRACE(logger, ...) logger->trace("[ " __FILE__ ":" SPDLOG_STR_HELPER(__LINE__) " ] " __VA_ARGS__)
  8. # endif
  9. #else
  10. # define SPDLOG_TRACE(logger, ...) (void)
  11. #endif
  12.  
  13. #ifdef SPDLOG_DEBUG_ON
  14. # define SPDLOG_DEBUG(logger, ...) logger->debug(__VA_ARGS__)
  15. #else
  16. # define SPDLOG_DEBUG(logger, ...) (void)
  17. #endif

4、同步和异步设置  Asynchronous logging

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

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

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

队列大小:

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

队列机制:

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

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

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

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

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

两种应对方式如下:

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

5、处理spdlog的异常  set_error_handler

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

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

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

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

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

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

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

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

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

或者单独drop某个logger

  1. spd::drop("console");
  2. spd::drop("basic_logger");

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

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

    参考文章: log库spdlog简介及使用 - 网络资源是无限的 - CSDN博客 http://blog.csdn.net/fengbingchun/article/details/78347105 ...

  2. c++ 日志输出库 spdlog 简介(4)- 多线程txt输出日志

    在上一节的代码中加入了向文本文件中写入日志的代码: UINT CMFCApplication1Dlg::Thread1(LPVOID pParam) { try{ size_t q_size = ; ...

  3. c++日志输出库 spdlog 简介(3)多线程控制台输出日志

    spdlog源码分析:https://www.cnblogs.com/eskylin/p/6483199.html spdlog的异步模式使得spdLog可以支持多线程,于是写了一个多线程的小例子: ...

  4. 细说Java主流日志工具库

    概述 在项目开发中,为了跟踪代码的运行情况,常常要使用日志来记录信息. 在Java世界,有很多的日志工具库来实现日志功能,避免了我们重复造轮子. 我们先来逐一了解一下主流日志工具. java.util ...

  5. Haproxy安装配置及日志输出问题

    简介: 软件负载均衡一般通过两种方式来实现:基于操作系统的软负载实现和基于第三方应用的软负载实现.LVS就是基于Linux操作系统实现的一种软负载,HAProxy就是开源的并且基于第三应用实现的软负载 ...

  6. Java主流日志工具库

    在项目开发中,为了跟踪代码的运行情况,常常要使用日志来记录信息.在Java世界,有很多的日志工具库来实现日志功能,避免了我们重复造轮子.我们先来逐一了解一下主流日志工具. 1.java.util.lo ...

  7. 基于java.util.logging实现轻量级日志记录库(增加根据当前类class初始化,修复线程池模型(javaEE)下的堆栈轨迹顺序与当前调用方法不一致问题)

    前言: 本章介绍自己写的基于java.util.logging的轻量级日志记录库(baseLog). 该版本的日志记录库犹如其名,baseLog,是个实现日志记录基本功能的小库,适合小型项目使用,方便 ...

  8. python的日志模块:logging;django的日志系统;django日志输出时间修改

    Django的log,主要是复用Python标准库中的logging模块,在settings.py中进行配置 源代码 1.__init__.py包含以下类: StreamHandler Formatt ...

  9. Python 日志输出

    昨天的任务是需要记录各操作的性能数据,所以需要用这种格式来输出日志:{"adb_start_time": 1480040663, "tag_name": &qu ...

随机推荐

  1. Python3执行DOS命令并截取其输出到一个列表字符串,同时写入一个文件

    #执行DOS命令并截取其输出到一个列表字符串,同时写入一个文件#这个功能很有用listing=os.popen('ipconfig').readlines()for i in listing: pri ...

  2. leetcode617

    这道题想了很久,并没有掌握思想,写了很多,也没有解决.先贴出思考的过程. class Solution { public: vector<TreeNode> v1; vector<T ...

  3. idea导入项目

    1. 2.导入项目 3.右键项目选择web 4.编辑添加tomcat 5.添加jar.包 6. 7.右键put into 8.安装tomcat 9.引入tomcat 10.把项目布署到tomcat

  4. jenkins Manage and Assign Roles使用

    1.安装插件  Role-based Authorization Strategy 2.使用插件 3.进入 Manage and Assign Roles  配置Pattern 匹配项目, 如果要匹配 ...

  5. js原型继承四步曲

    <sctript> //1.创建父类 function Parent(){ this.name = name; } Parent.prototype.age = 20; //2.创建子类 ...

  6. route命令详解

    1.   使用背景:需要接入两个网络,一个是部署环境所在内网环境,这个环境是上不了外网, 外网环境很可能是一个无线网络.如果两者都连接上,很可能导致有一方不能起作用,即外网或内网上不了,常常需要使用繁 ...

  7. python-imaging-tk : Depends: python-imaging (= 1.1.7-4ubuntu0.12.04.3) but 3.1.2-0ubuntu1.1 is to be installed E: Unable to corre

    最近,将电脑主机升级到ubuntu16.04,但是需要用到 python-imaging-tk,先是报错: import PIL.ImageTk as ImageTkImportError: No m ...

  8. C程序的编译与链接

    编译器驱动程序 编译器驱动程序可以在用户需要时调用语言预处理器.编译器.汇编器和链接器. 例如使用GNU编译系统,我们需要使用如下命令来调用GCC驱动程序: gcc -o main main.c 编译 ...

  9. linux 部分常用命令

    1.Linux 删除除了某个文件之外的所有文件 [root@localhost abc]# ls |grep -v 'a' |xargs rm -f 其中rm -f  !(a) 最为方便.如果保留a和 ...

  10. Cocos2dx Android工程的启动过程

    1.安卓工程下的设置启动activity为src下面的AppActivity,启动调用的onCreate并没有做过多的事情,只是调用了父类Cocos2dxActivity的onCreate.AppAc ...