easylogging++的那些事(四)源码分析(二)日志记录宏(四)偶尔日志宏
在上一篇我们介绍完了 easylogging++的 条件日志宏,今天我们来看看偶尔日志宏的实现.
CLOG_EVERY_N 宏
宏展开
CLOG_EVERY_N
宏定义如下:#define CLOG_EVERY_N(n, LEVEL, ...)\ C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__)
其中
##
是连字符,__VA_ARGS__
原样替换...
Info 日志宏 CLOG_EVERY_N(xxx, INFO, xxx)
用个具体的例子就一目了然了:
CLOG_EVERY_N(3, INFO, "default");
上面实际展开后为:
CINFO_EVERY_N(el::base::Writer, 3, el::base::DispatchAction::NormalLog, "default");
CINFO_EVERY_N
也是一个宏:#if ELPP_INFO_LOG #define CINFO_EVERY_N(writer, occasion, dispatchAction, ...)\ ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Info, dispatchAction, __VA_ARGS__) #else #define CINFO_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() #endif // ELPP_INFO_LOG
ELPP_INFO_LOG
宏和el::base::NullWriter
类在CLOG
宏展开 中已经介绍过了,这里就不多说了。
这里我们直接看ELPP_INFO_LOG
宏值为 1 的情况:ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Info, dispatchAction, __VA_ARGS__)
经过替换后为:
ELPP_WRITE_LOG_EVERY_N(el::base::Writer, 3, el::Level::Info, el::base::DispatchAction::NormalLog, "default");
ELPP_WRITE_LOG_EVERY_N
也是一个宏:#define ELPP_WRITE_LOG_EVERY_N(writer, occasion, level, dispatchAction, ...) \ ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion) && \ writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
展开后为:
ELPP->validateEveryNCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Info, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(el_getVALength("default"), "default");
el_getVALength
宏在CLOG
宏展开 中已经详细分析过了,表示可变参的数目,这里el_getVALength("default")
值为 1,再次替换后:ELPP->validateEveryNCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Info, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(1, "default");
其他日志级别宏的展开类似。
Trace 日志宏 CLOG_EVERY_N(xxx, TRACE, xxx)
用个具体的例子就一目了然了:
CLOG_EVERY_N(3, TRACE, "default");
上面的实际展开后为:
CTRACE_EVERY_N(el::base::Writer, 3, el::base::DispatchAction::NormalLog, "default");
CTRACE_EVERY_N
也是一个宏:#if ELPP_TRACE_LOG #define CTRACE_EVERY_N(writer, occasion, dispatchAction, ...)\ ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Trace, dispatchAction, __VA_ARGS__) #else #define CTRACE_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() #endif // ELPP_TRACE_LOG
ELPP_TRACE_LOG
宏和el::base::NullWriter
类在CLOG
宏展开 中已经介绍过了,这里就不多说了。
这里我们直接看ELPP_TRACE_LOG
宏值为 1 的情况:ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Trace, dispatchAction, __VA_ARGS__)
ELPP_WRITE_LOG_EVERY_N
宏在Info
日志宏中已经分析过了,这里直接看最终展开的结果:ELPP->validateEveryNCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Trace, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(1, "default");
Debug 日志宏 CLOG_EVERY_N(xxx, DEBUG, xxx)
用个具体的例子就一目了然了:
CLOG_EVERY_N(3, DEBUG, "default");
上面的实际展开后为:
CDEBUG_EVERY_N(el::base::Writer, 3, el::base::DispatchAction::NormalLog, "default");
CDEBUG_EVERY_N
也是一个宏:#if ELPP_DEBUG_LOG #define CDEBUG_EVERY_N(writer, occasion, dispatchAction, ...)\ ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Debug, dispatchAction, __VA_ARGS__) #else #define CDEBUG_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() #endif // ELPP_DEBUG_LOG
ELPP_DEBUG_LOG
宏和el::base::NullWriter
类在CLOG
宏展开 中已经介绍过了,这里就不多说了。
这里我们直接看ELPP_DEBUG_LOG
宏值为 1 的情况:ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Debug, dispatchAction, __VA_ARGS__)
ELPP_WRITE_LOG_EVERY_N
宏在Info
日志宏中已经分析过了,这里直接看最终展开的结果:ELPP->validateEveryNCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Debug, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(1, "default");
Fatal 日志宏 CLOG_EVERY_N(xxx, FATAL, xxx)
用个具体的例子就一目了然了:
CLOG_EVERY_N(3, FATAL, "default");
上面的实际展开后为:
CFATAL_EVERY_N(el::base::Writer, 3, el::base::DispatchAction::NormalLog, "default");
CFATAL_EVERY_N
也是一个宏:#if ELPP_FATAL_LOG #define CFATAL_EVERY_N(writer, occasion, dispatchAction, ...)\ ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Fatal, dispatchAction, __VA_ARGS__) #else #define CFATAL_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() #endif // ELPP_FATAL_LOG
ELPP_FATAL_LOG
宏和el::base::NullWriter
类在CLOG
宏展开 中已经介绍过了,这里就不多说了。
这里我们直接看ELPP_FATAL_LOG
宏值为 1 的情况:ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Fatal, dispatchAction, __VA_ARGS__)
ELPP_WRITE_LOG_EVERY_N
宏在Info
日志宏中已经分析过了,这里直接看最终展开的结果:ELPP->validateEveryNCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Fatal, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(1, "default");
Error 日志宏 CLOG_EVERY_N(xxx, ERROR, xxx)
用个具体的例子就一目了然了:
CLOG_EVERY_N(3, ERROR, "default");
上面的实际展开后为:
CERROR_EVERY_N(el::base::Writer, 3, el::base::DispatchAction::NormalLog, "default");
CERROR_EVERY_N
也是一个宏:#if ELPP_ERROR_LOG #define CERROR_EVERY_N(writer, occasion, dispatchAction, ...)\ ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Error, dispatchAction, __VA_ARGS__) #else #define CERROR_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() #endif // ELPP_ERROR_LOG
ELPP_ERROR_LOG
宏和el::base::NullWriter
类在CLOG
宏展开 中已经介绍过了,这里就不多说了。
这里我们直接看ELPP_ERROR_LOG
宏值为 1 的情况:ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Error, dispatchAction, __VA_ARGS__)
ELPP_WRITE_LOG_EVERY_N
宏在Info
日志宏中已经分析过了,这里直接看最终展开的结果:ELPP->validateEveryNCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Error, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(1, "default");
Warning 日志宏 CLOG_EVERY_N(xxx, WARNING, xxx)
用个具体的例子就一目了然了:
CLOG_EVERY_N(3, WARNING, "default");
上面的实际展开后为:
CWARNING_EVERY_N(el::base::Writer, 3, el::base::DispatchAction::NormalLog, "default");
CWARNING_EVERY_N
也是一个宏:#if ELPP_WARNING_LOG #define CWARNING_EVERY_N(writer, occasion, dispatchAction, ...)\ ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Warning, dispatchAction, __VA_ARGS__) #else #define CWARNING_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() #endif // ELPP_WARNING_LOG
ELPP_WARNING_LOG
宏和el::base::NullWriter
类在CLOG
宏展开 中已经介绍过了,这里就不多说了。
这里我们直接看ELPP_WARNING_LOG
宏值为 1 的情况:ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Warning, dispatchAction, __VA_ARGS__)
ELPP_WRITE_LOG_EVERY_N
宏在Info
日志宏中已经分析过了,这里直接看最终展开的结果:ELPP->validateEveryNCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Warning, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(1, "default");
源码剖析
上面所有日志级别宏的最终展开后的结果都类似,这个宏其实就是表示:
当ELPP->validateEveryNCounter(__FILE__, __LINE__, 3)
为true
时,执行el::base::Writer
对象的创建和初始化。el::base::Writer
类我们在CLOG
宏 Writer 对象的创建以及初始化、日志输出、日志信息的保存 已经仔细介绍过了,这里就不多说了。
当ELPP->validateEveryNCounter(__FILE__, __LINE__, 3)
为false
时,啥也不干。
ELPP
宏是 easylogging++的全局管理类,其定义如下:extern ELPP_EXPORT base::type::StoragePointer elStorage; #define ELPP el::base::elStorage
ELPP->validateEveryNCounter
的实现如下:inline bool validateEveryNCounter(const char* filename, base::type::LineNumber lineNumber, std::size_t occasion) { return hitCounters()->validateEveryN(filename, lineNumber, occasion); }
hitCounters()
返回的是指定文件指定行的用于是否记录日志的计数器。
validateEveryN
的实现如下:bool RegisteredHitCounters::validateEveryN(const char *filename, base::type::LineNumber lineNumber, std::size_t n) { base::threading::ScopedLock scopedLock(lock()); // 获取指定文件的指定行的统计次数 base::HitCounter *counter = get(filename, lineNumber); if (counter == nullptr) { registerNew(counter = new base::HitCounter(filename, lineNumber)); } // 统计次数超过阈值进行调整 counter->validateHitCounts(n); // 给定的偶尔记日志的次数有效并且调整后的统计次数符合条件则返回真 bool result = (n >= 1 && counter->hitCounts() != 0 && counter->hitCounts() % n == 0); return result; }
validateHitCounts
实现如下:/// @brief Validates hit counts and resets it if necessary inline void validateHitCounts(std::size_t n) { // 统计次数超过阈值时进行调整 if (m_hitCounts >= base::consts::kMaxLogPerCounter) { m_hitCounts = (n >= 1 ? base::consts::kMaxLogPerCounter % n : 0); } ++m_hitCounts; }
CLOG_AFTER_N 宏
宏展开
CLOG_AFTER_N
宏定义如下:#define CLOG_AFTER_N(n, LEVEL, ...)\ C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__)
其中
##
是连字符,__VA_ARGS__
原样替换...
Info 日志宏 CLOG_AFTER_N(xxx, INFO, xxx)
用个具体的例子就一目了然了:
CLOG_AFTER_N(3, INFO, "default");
上面实际展开后为:
CINFO_AFTER_N(el::base::Writer, 3, el::base::DispatchAction::NormalLog, "default");
CINFO_AFTER_N
也是一个宏:#if ELPP_INFO_LOG #define CINFO_AFTER_N(writer, n, dispatchAction, ...)\ ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__) #else #define CINFO_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() #endif // ELPP_INFO_LOG
ELPP_INFO_LOG
宏和el::base::NullWriter
类在CLOG
宏展开 中已经介绍过了,这里就不多说了。
这里我们直接看ELPP_INFO_LOG
宏值为 1 的情况:ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__)
经过替换后为:
ELPP_WRITE_LOG_AFTER_N(el::base::Writer, 3, el::Level::Info, el::base::DispatchAction::NormalLog, "default");
ELPP_WRITE_LOG_AFTER_N
也是一个宏:#define ELPP_WRITE_LOG_AFTER_N(writer, n, level, dispatchAction, ...) \ ELPP->validateAfterNCounter(__FILE__, __LINE__, n) && \ writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
展开后为:
ELPP->validateAfterNCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Info, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(el_getVALength("default"), "default");
el_getVALength
宏在CLOG
宏展开 中已经详细分析过了,表示可变参的数目,这里el_getVALength("default")
值为 1,再次替换后:ELPP->validateAfterNCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Info, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(1, "default");
其他日志级别宏的展开类似。
Trace 日志宏 CLOG_AFTER_N(xxx, TRACE, xxx)
用个具体的例子就一目了然了:
CLOG_AFTER_N(3, TRACE, "default");
上面实际展开后为:
CTRACE_AFTER_N(el::base::Writer, 3, el::base::DispatchAction::NormalLog, "default");
CTRACE_AFTER_N
也是一个宏:#if ELPP_TRACE_LOG #define CTRACE_AFTER_N(writer, n, dispatchAction, ...)\ ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__) #else #define CTRACE_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() #endif // ELPP_TRACE_LOG
ELPP_TRACE_LOG
宏和el::base::NullWriter
类在CLOG
宏展开 中已经介绍过了,这里就不多说了。
这里我们直接看ELPP_TRACE_LOG
宏值为 1 的情况:ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__)
经过替换后为:
ELPP_WRITE_LOG_AFTER_N(el::base::Writer, 3, el::Level::Trace, el::base::DispatchAction::NormalLog, "default");
ELPP_WRITE_LOG_AFTER_N
宏在Info
日志宏中已经详细介绍过了,这里直接看最终展开后的结果:ELPP->validateAfterNCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Trace, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(1, "default");
Debug 日志宏 CLOG_AFTER_N(xxx, DEBUG, xxx)
用个具体的例子就一目了然了:
CLOG_AFTER_N(3, DEBUG, "default");
上面实际展开后为:
CDEBUG_AFTER_N(el::base::Writer, 3, el::base::DispatchAction::NormalLog, "default");
CDEBUG_AFTER_N
也是一个宏:#if ELPP_DEBUG_LOG #define CDEBUG_AFTER_N(writer, n, dispatchAction, ...)\ ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__) #else #define CDEBUG_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() #endif // ELPP_DEBUG_LOG
ELPP_DEBUG_LOG
宏和el::base::NullWriter
类在CLOG
宏展开 中已经介绍过了,这里就不多说了。
这里我们直接看ELPP_DEBUG_LOG
宏值为 1 的情况:ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__)
经过替换后为:
ELPP_WRITE_LOG_AFTER_N(el::base::Writer, 3, el::Level::Debug, el::base::DispatchAction::NormalLog, "default");
ELPP_WRITE_LOG_AFTER_N
宏在Info
日志宏中已经详细介绍过了,这里直接看最终展开后的结果:ELPP->validateAfterNCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Debug, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(1, "default");
Fatal 日志宏 CLOG_AFTER_N(xxx, FATAL, xxx)
用个具体的例子就一目了然了:
CLOG_AFTER_N(3, FATAL, "default");
上面实际展开后为:
CFATAL_AFTER_N(el::base::Writer, 3, el::base::DispatchAction::NormalLog, "default");
CFATAL_AFTER_N
也是一个宏:#if ELPP_FATAL_LOG #define CFATAL_AFTER_N(writer, n, dispatchAction, ...)\ ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__) #else #define CFATAL_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() #endif // ELPP_FATAL_LOG
ELPP_FATAL_LOG
宏和el::base::NullWriter
类在CLOG
宏展开 中已经介绍过了,这里就不多说了。
这里我们直接看ELPP_FATAL_LOG
宏值为 1 的情况:ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__)
经过替换后为:
ELPP_WRITE_LOG_AFTER_N(el::base::Writer, 3, el::Level::Fatal, el::base::DispatchAction::NormalLog, "default");
ELPP_WRITE_LOG_AFTER_N
宏在Info
日志宏中已经详细介绍过了,这里直接看最终展开后的结果:ELPP->validateAfterNCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Fatal, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(1, "default");
Error 日志宏 CLOG_AFTER_N(xxx, ERROR, xxx)
用个具体的例子就一目了然了:
CLOG_AFTER_N(3, ERROR, "default");
上面实际展开后为:
CERROR_AFTER_N(el::base::Writer, 3, el::base::DispatchAction::NormalLog, "default");
CERROR_AFTER_N
也是一个宏:#if ELPP_ERROR_LOG #define CERROR_AFTER_N(writer, n, dispatchAction, ...)\ ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__) #else #define CERROR_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() #endif // ELPP_ERROR_LOG
ELPP_ERROR_LOG
宏和el::base::NullWriter
类在CLOG
宏展开 中已经介绍过了,这里就不多说了。
这里我们直接看ELPP_ERROR_LOG
宏值为 1 的情况:ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__)
经过替换后为:
ELPP_WRITE_LOG_AFTER_N(el::base::Writer, 3, el::Level::Error, el::base::DispatchAction::NormalLog, "default");
ELPP_WRITE_LOG_AFTER_N
宏在Info
日志宏中已经详细介绍过了,这里直接看最终展开后的结果:ELPP->validateAfterNCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Error, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(1, "default");
Warning 日志宏 CLOG_AFTER_N(xxx, WARNING, xxx)
用个具体的例子就一目了然了:
CLOG_AFTER_N(3, WARNING, "default");
上面实际展开后为:
CWARNING_AFTER_N(el::base::Writer, 3, el::base::DispatchAction::NormalLog, "default");
CWARNING_AFTER_N
也是一个宏:#if ELPP_WARNING_LOG #define CWARNING_AFTER_N(writer, n, dispatchAction, ...)\ ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__) #else #define CWARNING_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() #endif // ELPP_WARNING_LOG
ELPP_WARNING_LOG
宏和el::base::NullWriter
类在CLOG
宏展开 中已经介绍过了,这里就不多说了。
这里我们直接看ELPP_WARNING_LOG
宏值为 1 的情况:ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__)
经过替换后为:
ELPP_WRITE_LOG_AFTER_N(el::base::Writer, 3, el::Level::Warning, el::base::DispatchAction::NormalLog, "default");
ELPP_WRITE_LOG_AFTER_N
宏在Info
日志宏中已经详细介绍过了,这里直接看最终展开后的结果:ELPP->validateAfterNCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Warning, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(1, "default");
源码剖析
上面所有日志级别宏的最终展开后的结果都类似,这个宏其实就是表示:
当
ELPP->validateAfterNCounter(__FILE__, __LINE__, 3)
为true
时,执行el::base::Writer
对象的创建和初始化。el::base::Writer
类我们在CLOG
宏 Writer 对象的创建以及初始化、日志输出、日志信息的保存 已经仔细介绍过了,这里就不多说了。
当ELPP->validateAfterNCounter(__FILE__, __LINE__, 3)
为false
时,啥也不干。
ELPP
宏在前面已经介绍过了,是 easylogging++的全局管理类。
ELPP->validateAfterNCounter
的实现如下:inline bool validateAfterNCounter(const char* filename, base::type::LineNumber lineNumber, std::size_t n) { return hitCounters()->validateAfterN(filename, lineNumber, n); }
hitCounters()
返回的是指定文件指定行的用于是否记录日志的计数器。
validateAfterN
的实现如下:/// @brief Validates counter for hits >= N, i.e, registers new if does not exist otherwise updates original one /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned bool RegisteredHitCounters::validateAfterN(const char* filename, base::type::LineNumber lineNumber, std::size_t n) { base::threading::ScopedLock scopedLock(lock()); //获取指定文件的指定行的统计次数 base::HitCounter* counter = get(filename, lineNumber); if (counter == nullptr) { registerNew(counter = new base::HitCounter(filename, lineNumber)); } // Do not use validateHitCounts here since we do not want to reset counter here // Note the >= instead of > because we are incrementing // after this check if (counter->hitCounts() >= n) return true; counter->increment(); return false; }
increment
的实现如下:inline void increment(void) { ++m_hitCounts; }
实现很简单,没什么好多说的。
CLOG_N_TIMES 宏
宏展开
CLOG_N_TIMES
宏定义如下:#define CLOG_N_TIMES(n, LEVEL, ...)\ C##LEVEL##_N_TIMES(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__)
其中
##
是连字符,__VA_ARGS__
原样替换...
Info 日志宏 CLOG_N_TIMES(xxx, INFO, xxx)
用个具体的例子就一目了然了:
CLOG_N_TIMES(3, INFO, "default");
上面实际展开后为:
CINFO_N_TIMES(el::base::Writer, 3, el::base::DispatchAction::NormalLog, "default");
CINFO_N_TIMES
也是一个宏:#if ELPP_INFO_LOG #define CINFO_N_TIMES(writer, n, dispatchAction, ...)\ ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__) #else #define CINFO_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() #endif // ELPP_INFO_LOG
ELPP_INFO_LOG
宏和el::base::NullWriter
类在CLOG
宏展开 中已经介绍过了,这里就不多说了。
这里我们直接看ELPP_INFO_LOG
宏值为 1 的情况:ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__)
经过替换后为:
ELPP_WRITE_LOG_N_TIMES(el::base::Writer, 3, el::Level::Info, el::base::DispatchAction::NormalLog, "default");
ELPP_WRITE_LOG_N_TIMES
也是一个宏:#define ELPP_WRITE_LOG_N_TIMES(writer, n, level, dispatchAction, ...) \ ELPP->validateNTimesCounter(__FILE__, __LINE__, n) && \ writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
展开后为:
ELPP->validateNTimesCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Info, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(el_getVALength("default"), "default");
el_getVALength
宏在CLOG
宏展开 中已经详细分析过了,表示可变参的数目,这里el_getVALength("default")
值为 1,再次替换后:ELPP->validateNTimesCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Info, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(1, "default");
其他日志级别宏的展开类似。
Trace 日志宏 CLOG_N_TIMES(xxx, TRACE, xxx)
用个具体的例子就一目了然了:
CLOG_N_TIMES(3, TRACE, "default");
上面实际展开后为:
CTRACE_N_TIMES(el::base::Writer, 3, el::base::DispatchAction::NormalLog, "default");
CTRACE_N_TIMES
也是一个宏:#if ELPP_TRACE_LOG #define CTRACE_N_TIMES(writer, n, dispatchAction, ...)\ ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__) #else #define CTRACE_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() #endif // ELPP_TRACE_LOG
ELPP_TRACE_LOG
宏和el::base::NullWriter
类在CLOG
宏展开 中已经介绍过了,这里就不多说了。
这里我们直接看ELPP_TRACE_LOG
宏值为 1 的情况:ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__)
经过替换后为:
ELPP_WRITE_LOG_N_TIMES(el::base::Writer, 3, el::Level::Trace, el::base::DispatchAction::NormalLog, "default");
ELPP_WRITE_LOG_N_TIMES
宏在Info
日志宏中已经详细介绍过了,这里直接看最终最终展开的结果:ELPP->validateNTimesCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Trace, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(1, "default");
Debug 日志宏 CLOG_N_TIMES(xxx, DEBUG, xxx)
用个具体的例子就一目了然了:
CLOG_N_TIMES(3, DEBUG, "default");
上面实际展开后为:
CDEBUG_N_TIMES(el::base::Writer, 3, el::base::DispatchAction::NormalLog, "default");
CDEBUG_N_TIMES
也是一个宏:#if ELPP_DEBUG_LOG #define CDEBUG_N_TIMES(writer, n, dispatchAction, ...)\ ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__) #else #define CDEBUG_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() #endif // ELPP_DEBUG_LOG
ELPP_DEBUG_LOG
宏和el::base::NullWriter
类在CLOG
宏展开 中已经介绍过了,这里就不多说了。
这里我们直接看ELPP_DEBUG_LOG
宏值为 1 的情况:ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__)
经过替换后为:
ELPP_WRITE_LOG_N_TIMES(el::base::Writer, 3, el::Level::Debug, el::base::DispatchAction::NormalLog, "default");
ELPP_WRITE_LOG_N_TIMES
宏在Info
日志宏中已经详细介绍过了,这里直接看最终最终展开的结果:ELPP->validateNTimesCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Debug, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(1, "default");
Fatal 日志宏 CLOG_N_TIMES(xxx, FATAL, xxx)
用个具体的例子就一目了然了:
CLOG_N_TIMES(3, FATAL, "default");
上面实际展开后为:
CFATAL_N_TIMES(el::base::Writer, 3, el::base::DispatchAction::NormalLog, "default");
CFATAL_N_TIMES
也是一个宏:#if ELPP_FATAL_LOG #define CFATAL_N_TIMES(writer, n, dispatchAction, ...)\ ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__) #else #define CFATAL_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() #endif // ELPP_FATAL_LOG
ELPP_FATAL_LOG
宏和el::base::NullWriter
类在CLOG
宏展开 中已经介绍过了,这里就不多说了。
这里我们直接看ELPP_FATAL_LOG
宏值为 1 的情况:ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__)
经过替换后为:
ELPP_WRITE_LOG_N_TIMES(el::base::Writer, 3, el::Level::Fatal, el::base::DispatchAction::NormalLog, "default");
ELPP_WRITE_LOG_N_TIMES
宏在Info
日志宏中已经详细介绍过了,这里直接看最终最终展开的结果:ELPP->validateNTimesCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Fatal, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(1, "default");
Error 日志宏 CLOG_N_TIMES(xxx, ERROR, xxx)
用个具体的例子就一目了然了:
CLOG_N_TIMES(3, ERROR, "default");
上面实际展开后为:
CERROR_N_TIMES(el::base::Writer, 3, el::base::DispatchAction::NormalLog, "default");
CERROR_N_TIMES
也是一个宏:#if ELPP_ERROR_LOG #define CERROR_N_TIMES(writer, n, dispatchAction, ...)\ ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__) #else #define CERROR_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() #endif // ELPP_ERROR_LOG
ELPP_ERROR_LOG
宏和el::base::NullWriter
类在CLOG
宏展开 中已经介绍过了,这里就不多说了。
这里我们直接看ELPP_ERROR_LOG
宏值为 1 的情况:ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__)
经过替换后为:
ELPP_WRITE_LOG_N_TIMES(el::base::Writer, 3, el::Level::Error, el::base::DispatchAction::NormalLog, "default");
ELPP_WRITE_LOG_N_TIMES
宏在Info
日志宏中已经详细介绍过了,这里直接看最终最终展开的结果:ELPP->validateNTimesCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Error, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(1, "default");
Warning 日志宏 CLOG_N_TIMES(xxx, WARNING, xxx)
用个具体的例子就一目了然了:
CLOG_N_TIMES(3, WARNING, "default");
上面实际展开后为:
CWARNING_N_TIMES(el::base::Writer, 3, el::base::DispatchAction::NormalLog, "default");
CWARNING_N_TIMES
也是一个宏:#if ELPP_WARNING_LOG #define CWARNING_N_TIMES(writer, n, dispatchAction, ...)\ ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__) #else #define CWARNING_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() #endif // ELPP_WARNING_LOG
ELPP_WARNING_LOG
宏和el::base::NullWriter
类在CLOG
宏展开 中已经介绍过了,这里就不多说了。
这里我们直接看ELPP_WARNING_LOG
宏值为 1 的情况:ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__)
经过替换后为:
ELPP_WRITE_LOG_N_TIMES(el::base::Writer, 3, el::Level::Warning, el::base::DispatchAction::NormalLog, "default");
ELPP_WRITE_LOG_N_TIMES
宏在Info
日志宏中已经详细介绍过了,这里直接看最终最终展开的结果:ELPP->validateNTimesCounter(__FILE__, __LINE__, 3) && el::base::Writer(el::Level::Warning, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(1, "default");
源码剖析
上面所有日志级别宏的最终展开后的结果都类似,这个宏其实就是表示:
当
ELPP->validateNTimesCounter(__FILE__, __LINE__, 3)
为真时,执行el::base::Writer
对象的创建和初始化。el::base::Writer
类我们在CLOG
宏 Writer 对象的创建以及初始化、日志输出、日志信息的保存 已经仔细介绍过了,这里就不多说了。
当ELPP->validateNTimesCounter(__FILE__, __LINE__, 3)
为假时,啥也不干。
ELPP
宏在前面已经介绍过了,是 easylogging++的全局管理类。
ELPP->validateNTimesCounter
的实现如下:inline bool validateNTimesCounter(const char* filename, base::type::LineNumber lineNumber, std::size_t n) { return hitCounters()->validateNTimes(filename, lineNumber, n); }
hitCounters()
返回的是指定文件指定行的用于是否记录日志的计数器。
validateNTimes
的实现如下:/// @brief Validates counter for hits are <= n, i.e, registers new if does not exist otherwise updates original one /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned bool RegisteredHitCounters::validateNTimes(const char* filename, base::type::LineNumber lineNumber, std::size_t n) { base::threading::ScopedLock scopedLock(lock()); base::HitCounter* counter = get(filename, lineNumber); if (counter == nullptr) { registerNew(counter = new base::HitCounter(filename, lineNumber)); } //increment接口在前面 CLOG_AFTER_N宏中已经介绍过了 counter->increment(); // Do not use validateHitCounts here since we do not want to reset counter here if (counter->hitCounts() <= n) return true; return false; }
实现很简单,没什么好多说的。
CSYSLOG_EVERY_N 宏
CSYSLOG_EVERY_N
定义如下:#define CSYSLOG_EVERY_N(n, LEVEL, ...) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__)
C##LEVEL##_EVERY_N
相关宏前面已经多次介绍过了。
CSYSLOG_AFTER_N 宏
CSYSLOG_AFTER_N
定义如下:#define CSYSLOG_AFTER_N(n, LEVEL, ...) C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__)
C##LEVEL##_AFTER_N
相关宏前面已经多次介绍过了。
CSYSLOG_N_TIMES 宏
CSYSLOG_N_TIMES
定义如下:#define CSYSLOG_N_TIMES(n, LEVEL, ...) C##LEVEL##_N_TIMES(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__)
C##LEVEL##_N_TIMES
相关宏前面已经多次介绍过了。
LOG_EVERY_N 宏
LOG_EVERY_N
定义如下:#define LOG_EVERY_N(n, LEVEL) CLOG_EVERY_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID)
CLOG_EVERY_N
宏前面已经介绍过了。
LOG_AFTER_N 宏
LOG_AFTER_N
定义如下:#define LOG_AFTER_N(n, LEVEL) CLOG_AFTER_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID)
CLOG_AFTER_N
宏前面已经介绍过了。
LOG_N_TIMES 宏
LOG_N_TIMES
定义如下:#define LOG_N_TIMES(n, LEVEL) CLOG_N_TIMES(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID)
CLOG_N_TIMES
宏前面已经介绍过了。
SYSLOG_EVERY_N 宏
SYSLOG_EVERY_N
定义如下:#define SYSLOG_EVERY_N(n, LEVEL) CSYSLOG_EVERY_N(n, LEVEL, el::base::consts::kSysLogLoggerId)
CSYSLOG_EVERY_N
宏前面已经介绍过了。
SYSLOG_AFTER_N 宏
SYSLOG_AFTER_N
定义如下:#define SYSLOG_AFTER_N(n, LEVEL) CSYSLOG_AFTER_N(n, LEVEL, el::base::consts::kSysLogLoggerId)
CSYSLOG_AFTER_N
宏前面已经介绍过了。
SYSLOG_N_TIMES 宏
SYSLOG_N_TIMES
定义如下:#define SYSLOG_N_TIMES(n, LEVEL) CSYSLOG_N_TIMES(n, LEVEL, el::base::consts::kSysLogLoggerId)
CSYSLOG_N_TIMES
宏前面已经介绍过了。
至此,偶尔日志宏就介绍完了,下一篇我们开始介绍检查宏。
本文来自博客园,作者:节奏自由,转载请注明原文链接:https://www.cnblogs.com/DesignLife/p/16934294.html