C++ Simple Message/Logging Class
在 Qt的源码与Protobuf 的代码中,看到相同的简单消息(日志)输出的类实现,基本思路是使用宏定义,重载临时类对象,调用类方法或者通过析构函数自动调用输出方法,实现消息输出。这里以 Protobuf 的LogMessage 类为例,简单描述实现方法。
类定义很简单,主要是构造函数、重载的 operator<< 操作符、Finish方法。构造函数传入日志等级、文件名及行号,为输出用。重载的 << 操作符为了流式输出。在后边实现了个私有的 Finish 方法,该方法简单粗暴,就是调用输出函数,如果是 Fatal 等级输出,还会抛出异常或者 abort。其定义如下:
enum LogLevel {
LOGLEVEL_INFO, // Informational. This is never actually used by
// libprotobuf.
LOGLEVEL_WARNING, // Warns about issues that, although not technically a
// problem now, could cause problems in the future. For
// example, a // warning will be printed when parsing a
// message that is near the message size limit.
LOGLEVEL_ERROR, // An error occurred which should never happen during
// normal use.
LOGLEVEL_FATAL, // An error occurred from which the library cannot
// recover. This usually indicates a programming error
// in the code which calls the library, especially when
// compiled in debug mode.
};
class LIBPROTOBUF_EXPORT LogMessage {
public:
LogMessage(LogLevel level, const char* filename, int line);
~LogMessage();
LogMessage& operator<<(const std::string& value);
LogMessage& operator<<(const char* value);
LogMessage& operator<<(char value);
LogMessage& operator<<(int value);
LogMessage& operator<<(uint value);
LogMessage& operator<<(long value);
LogMessage& operator<<(unsigned long value);
LogMessage& operator<<(long long value);
LogMessage& operator<<(unsigned long long value);
LogMessage& operator<<(double value);
LogMessage& operator<<(void* value);
LogMessage& operator<<(const StringPiece& value);
LogMessage& operator<<(const ::google::protobuf::util::Status& status);
LogMessage& operator<<(const uint128& value);
private:
friend class LogFinisher;
void Finish();
LogLevel level_;
const char* filename_;
int line_;
std::string message_;
};
同时实现了一个 LogFinisher 类,只重载了 operator= 操作符,该方法只是调用 LogMessage 的 Finish 方法。
class LIBPROTOBUF_EXPORT LogFinisher {
public:
void operator=(LogMessage& other) {
other.Finish();
}
};
再者实现方便使用的宏定义,定义如下所示。主要为 GOOGLE_LOG 宏,该宏构造 LogMessage 临时对象,调用 LogFinisher 的 operator= 方法,实现消息输出。在Qt 的代码中,并没有实现类似 LogFinisher 的类,直接构造了MessageLog 临时对象,在对象析构时调用输出函数,临时对象生命周期会在构造完执行析构,执行消息输出。以下宏定义中还定义了 GOOGLE_LOG_IF ,即条件为 true 时,什么都不做 (void)0,为 false时调用 GOOGLE_LOG。
#define GOOGLE_LOG(LEVEL) \
::google::protobuf::internal::LogFinisher() = \
::google::protobuf::internal::LogMessage( \
::google::protobuf::LOGLEVEL_##LEVEL, __FILE__, __LINE__)
#define GOOGLE_LOG_IF(LEVEL, CONDITION) \
!(CONDITION) ? (void) : GOOGLE_LOG(LEVEL) #define GOOGLE_CHECK(EXPRESSION) \
GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": "
#define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(::google::protobuf::internal::IsOk(A))
#define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B))
#define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B))
#define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) < (B))
#define GOOGLE_CHECK_LE(A, B) GOOGLE_CHECK((A) <= (B))
#define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK((A) > (B))
#define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK((A) >= (B))
通过以上实现,则可以在代码中使用以下形式进行消息输出或者断言。第一行直接输出 "Hello sunshy",额,sunshy 是寡人姓名拼音的简拼,第二行在var0 和 var1 不相等时输出后边的消息,同时抛异常或者abort,相等时则 do nothing
GOOGLE_LOG(INFO)<< "Hello " <<"sunshy\n";
GOOGLE_CHECK_EQ(var0, var1)<<" var0 not equal var\n";
最新工作的事心有不畅,随便写写,以遣胸怀
C++ Simple Message/Logging Class的更多相关文章
- Recommended Settings for Tracing and Message Logging
https://docs.microsoft.com/en-us/dotnet/framework/wcf/diagnostics/tracing/recommended-settings-for-t ...
- Python自动化运维之9、模块之sys、os、hashlib、random、time&datetime、logging、subprocess
python模块 用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需 ...
- Taxonomy of class loader problems encountered when using Jakarta Commons Logging(转)
Acknowledgments I would like to thank Jacob Kjome for reviewing early drafts of this document. His c ...
- python标准库-日志logging
1.模块级别 先看一下logging模块的日志级别特点,共分6个等级. 可以手工设置当前日志的默认等级(warn),当日志输出的等级高于默认等级时,日志输出到屏幕,否则不输出. #!/usr/bin/ ...
- python之配置logging的几种方式
作为开发者,我们可以通过以下3中方式来配置logging: 1)使用Python代码显式的创建loggers, handlers和formatters并分别调用它们的配置函数: 2)创建一个日志配置文 ...
- 以打印日志为荣之logging模块详细使用
啄木鸟社区里的Pythonic八荣八耻有一条: 以打印日志为荣 , 以单步跟踪为耻; 很多程序都有记录日志的需求,并且日志中包含的信息既有正常的程序访问日志,还可能有错误.警告等信息输出,python ...
- python3之xml&ConfigParser&hashlib&Subprocess&logging模块
1.xml模块 XML 指可扩展标记语言(eXtensible Markup Language),标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言. XML 被设计用来传输和存储 ...
- Python之配置日志的几种方式(logging模块)
原文:https://blog.csdn.net/WZ18810463869/article/details/81147167 作为开发者,我们可以通过以下3种方式来配置logging: 1)使用Py ...
- python模块之logging模块
1. 低配版 # 指定显示信息格式 import logging logging.basicConfig( level=20, # 设置显示或写入的起始级别 format="%(asctim ...
随机推荐
- E20170505-ms
respectively adv. 分别,各自,顺序 为,依次为 encryption n.加密 corresponding adj. 符合的,相应的,相关的 correspond v. 通信,符合, ...
- bzoj 2023: [Usaco2005 Nov]Ant Counting 数蚂蚁【生成函数||dp】
用生成函数套路推一推,推完老想NTT--实际上把这个多项式乘法看成dp然后前缀和优化一下即可 #include<iostream> #include<cstdio> using ...
- bzoj 2716 [Violet 3]天使玩偶 【CDQ分治】
KD-tree可做,但是我不会暂时不考虑 大意:在二维平面内,给定n个点,m个操作.操作A:加入一个点:操作B:询问一个点与平面上加入的点的最近距离 不封装会T不封装会T不封装会T不封装会T不封装会 ...
- iOS UITextView 设置圆角边框线
textView.layer.borderColor = UIColor.lightGray.cgColor textView.layer.cornerRadius = 4 textView.laye ...
- the little schemer 笔记(6)
第六章 Shadows 1 是算术表达式吗 是 3 是算术表达式吗 是的 1+3 是算术表达式吗 是的 1+3×4 是算术表达式吗 当然是 cookie 是算术表达式吗 是啊,你需要来一块吗 e那么 ...
- DP HDOJ 5492 Find a path
题目传送门 题意:从(1, 1)走到(n, m),每次往右或往下走,问(N+M−1)∑(Ai−Aavg)2 的最小值 分析:展开式子得到(N+M−1)∑(Ai2) - (∑(Ai))2的最小值.用普通 ...
- (转)生产者/消费者问题的多种Java实现方式
参考来源:http://blog.csdn.net/monkey_d_meng/article/details/6251879/ 生产者/消费者问题的多种Java实现方式 实质上,很多后台服务程序并发 ...
- P3717 [AHOI2017初中组]cover
题目背景 以下为不影响题意的简化版题目. 题目描述 一个n*n的网格图上有m个探测器,每个探测器有个探测半径r,问这n*n个点中有多少个点能被探测到. 输入输出格式 输入格式: 第一行3个整数n,m, ...
- 清理xcode缓存
code版本:8.3.3 iOS版本:10.3.2 移除 Xcode 运行安装 APP 产生的缓存文件(DerivedData) 只要重新运行Xcode就一定会重新生成,而且会随着运行程序的增多,占用 ...
- Performance engineering introduction
1.Performance Software performance is one of software quality attributes, it equal to efficiency w ...