easylogging++学习记录(二):流式日志
easylogging++日志库流式日志的写入,依赖于el::base::Writer类的析构,以debug日志为例:具体代码如下:
#define LOG(LEVEL) CLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID)
#define CLOG(LEVEL, ...)\
C##LEVEL(el::base::Writer, el::base::DispatchAction::NormalLog, __VA_ARGS__)
#if ELPP_DEBUG_LOG
# define CDEBUG(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Debug, dispatchAction, __VA_ARGS__) #define ELPP_WRITE_LOG(writer, level, dispatchAction, ...) \
writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
宏替换之后就是调用了Writer类的一个构造函数和一个construct()成员函数,等同于下面代码:
el::base::Writer(...).construct(...)
单独调用一个构造函数的话,会产生一个临时对象,在语句结束后,这个临时对象会被析构,进而触发析构函数中的日志写入逻辑,可以通过下列代码进行验证:
#include <iostream>
#include <sstream> class A
{
public:
A() { } ~A()
{
std::cout << m_ss.str() << std::endl;
} template<typename T>
A& operator << (const T& t)
{
m_ss << t;
return *this;
} private:
std::ostringstream m_ss;
}; #define SLOG() LOG(A) #define LOG(a) \
a() class B
{
public:
B() {}
~B()
{
std::cout << "~B()" << std::endl;
}
}; int main()
{
std::cout << ".........begin........." << std::endl;
SLOG() << "first....";
B();
std::cout << "..........middle......." << std::endl;
B b;
b = B();
std::cout << ".........end.........." << std::endl;
return ;
}
以上代码编译输出结果如下:
$ g++ macro.cpp -o main
$ ./main
.........begin.........
first....
~B()
..........middle.......
~B()
.........end..........
~B()
begin和middle之间两次单独调用构造函数的地方产生的临时对象,都在语句结束后被析构了,在middle和end之间,47行处,调用了构造函数构造出一个临时变量,然后通过赋值构造函数赋值给变量b,随即临时变量被析构,而变量b直到main函数结束才被析构掉。
总而言之,要对easylogging++做一层封装并保持其流式日志的特性,可以通过同样的方式,在析构函数上做手脚。
easylogging++学习记录(二):流式日志的更多相关文章
- Material Calendar View 学习记录(二)
Material Calendar View 学习记录(二) github link: material-calendarview; 在学习记录一中简单翻译了该开源项目的README.md文档.接下来 ...
- Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客
==他的博客应该不错,没有细看 Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客 http://blog.csdn.net/u012706811/article/det ...
- JavaScript学习记录二
title: JavaScript学习记录二 toc: true date: 2018-09-13 10:14:53 --<JavaScript高级程序设计(第2版)>学习笔记 要多查阅M ...
- 2.VUE前端框架学习记录二
VUE前端框架学习记录二:Vue核心基础2(完结)文字信息没办法描述清楚,主要看编码实战里面,有附带有一个完整可用的Html页面,有需要的同学到脑图里面自取.脑图地址http://naotu.baid ...
- 大数据学习:storm流式计算
Storm是一个分布式的.高容错的实时计算系统.Storm适用的场景: 1.Storm可以用来用来处理源源不断的消息,并将处理之后的结果保存到持久化介质中. 2.由于Storm的处理组件都是分布式的, ...
- JDK8新特性(二) 流式编程Stream
流式编程是1.8中的新特性,基于常用的四种函数式接口以及Lambda表达式对集合类数据进行类似流水线一般的操作 流式编程分为大概三个步骤:获取流 → 操作流 → 返回操作结果 流的获取方式 这里先了解 ...
- Java学习:Stream流式思想
Stream流 Java 8 API添加了一种新的机制——Stream(流).Stream和IO流不是一回事. 流式思想:像生产流水线一样,一个操作接一个操作. 使用Stream流的步骤:数据源→转换 ...
- JAVA NIO学习记录2-非阻塞式网络通信
一.阻塞与非阻塞 传统的IO 流都是阻塞式的.也就是说,当一个线程调用read() 或write() 时,该线程被阻塞,直到有一些数据被读取或写入,该线程在此期间不能执行其他任务.因此,在完成网络通信 ...
- easylogging++学习记录(一):接入
easylogging++是一个非常轻量级并且非常高效的一个日志库,支持文件配置,支持线程安全,并且其自定义格式非常的方便,最关键的是,其所有代码都集中在一个.h头文件之中,完全不需要引用第三方库,接 ...
随机推荐
- HAWQ取代传统数仓实践(八)——维度表技术之角色扮演维度
单个物理维度可以被事实表多次引用,每个引用连接逻辑上存在差异的角色维度.例如,事实表可以有多个日期,每个日期通过外键引用不同的日期维度,原则上每个外键表示不同的日期维度视图,这样引用具有不同的含义.这 ...
- apply 无循环拼接数组
apply()第二个参数只能是数组,这个数组将作为参数传给原函数的参数列表arguments. 其实在实际开发中,JS 继承的方法并不止这一种,使用原型链继承是更加常用的方式,此外还有构造函数继承,这 ...
- 关于this指向问题的总结【转自秘密花园】
this 的工作原理 JavaScript 有一套完全不同于其它语言的对 this 的处理机制. 在五种不同的情况下 ,this 指向的各不相同. 第一种:全局范围内 this; 当在全部范围内使用 ...
- NOIP模拟题 管道
题目大意 给定$n$个点的无向图,求它的$Dfs$序方案数$n\leq 18$ 题解 状压$Dp+$记忆化搜索. 设$F_{i,now}$表示到达$i$其中$now$集合代表的点集已经遍历过,还需要遍 ...
- Block Towers (思维实现)
个人心得:这题没怎么看,题意难懂.后面比完再看的时候发现很好做但是怎么卡时间是个问题. 题意:就是有m个可以用2层积木的,n个可以用三层积木的,但是他们不允许重复所以可以无限添加. 比如 3 2 一开 ...
- 关于matlab浮点转定点总结
1,算式长度不应该太长,否则在转换过程中提示位宽超过128位,(用的64位matlab),长算式改为短算式就可以了. 2,不要过于相信推荐字长,有些地方需要更高的精度,如果用推荐字长,可能结果误差较大 ...
- LA2797 Monster Trap
题意 PDF 分析 可以考虑建图,跑迷宫. 然后以线段端点,原点,和无穷大点建图,有边的条件是两点连线和墙没有交点. 但是对两个线段的交点处理就会有问题,所以把线段延长.另外还需要判断延长后在墙上,舍 ...
- RbbitMQ基础知识
MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们.消息传递指的是程序之间 ...
- Collections排序
0.前言 ThreeSet的底层实现是红黑树,它在创建set的过程中实现排序.Collections.sort是在对整个集合进行排序,按道理来说使用TreeSet插入集合元素直至建立整个TreeSet ...
- FastAdmin 增删改查在哪里?
FastAdmin 增删改查在哪里? 一键生成 CRUD think crud -t test -u 1 执行命令合会在 controller 下生成 Test.php 控制器. 但是这个文件里确看不 ...