日志库EasyLogging++学习系列(7)—— 记录方式详解
来源:互联网 发布:蜘蛛爬行软件 编辑:程序博客网 时间:2024/06/15 11:46
在前面所列文章的演示代码中,其实已经展示了一部分记录日志的方式。为了使用方便,在 Easylogging++ 中,通过使用宏的集合来完成日志记录。
普通日志记录
对于普通的日志记录,我们可以选择以下两种比较常用的方式:
LOG(LEVEL)
CLOG(LEVEL, logger ID)
- #include "easylogging++.h"
- INITIALIZE_EASYLOGGINGPP
- int main(int argc, char** argv)
- {
- /// 可以直接使用,不记录任何日志信息
- LOG(INFO);
- CLOG(INFO, "default");
- LOG(INFO) << "Here is very simple example.";
- CLOG(INFO, "default") << "Here is very simple example.";
- system("pause");
- return 0;
- }
- #define ELPP_DEFAULT_LOGGER "testlog"
- #include "easylogging++.h"
- INITIALIZE_EASYLOGGINGPP
- int main(int argc, char** argv)
- {
- /// 使用前,注册ID为testlog的日志记录器
- el::Logger* newLogger = el::Loggers::getLogger("testlog");
- LOG(INFO) << "Here is very simple example.";
- system("pause");
- return 0;
- }
条件日志记录
条件日志就是只有当满足某一个条件的时候才进行日志记录,否则将忽略记录。下面是记录条件日志的两个宏定义:
LOG_IF(condition, LEVEL)
CLOG_IF(condition, LEVEL, logger ID)
上面两个宏定义中 condition 条件为真时,日志信息才被记录,在某些应用场景下这会显得十分便利,下面的代码演示了条件日志宏定义的用法:
- #include "easylogging++.h"
- INITIALIZE_EASYLOGGINGPP
- int main(int argc, char** argv)
- {
- /// 下面这三个日志,只有第一个会输出
- LOG_IF(1 == 1, INFO) << "1 is equal to 1";
- LOG_IF(1 > 2, INFO) << "1 is greater than 2";
- LOG_IF(1 == 2, DEBUG) << "1 is equal to 2";
- system("pause");
- return 0;
- }
偶然日志记录
偶然日志可以分为以下三种常见的情况,具体使用方法请参考示例代码:
- 每 N 次记录一次日志,对应的宏定义是:LOG_EVERY_N(n, LEVEL) 或者 CLOG_EVERY_N(n, LEVEL, logger ID)
- 当计数达到 N 次之后,才开始记录日志,对应的宏定义是:LOG_AFTER_N(n, LEVEL)
- 当记录次数达到 N 次之后,就不再记录日志信息,对应的宏定义是:LOG_N_TIMES(n, LEVEL)
- #include "easylogging++.h"
- INITIALIZE_EASYLOGGINGPP
- int main(int argc, char** argv)
- {
- /// 每 N 次记录一次日志
- for (int i = 1; i <= 200; ++i)
- {
- LOG_EVERY_N(20, INFO) << "LOG_EVERY_N i = " << i;
- LOG_EVERY_N(100, INFO) << "LOG_EVERY_N Current position is " << ELPP_COUNTER_POS;
- }
- /// 当计数达到 N 次之后,才开始记录日志
- for (int i = 1; i <= 10; ++i)
- {
- LOG_AFTER_N(6, INFO) << "LOG_AFTER_N i = " << i;
- }
- /// 当记录次数达到 N 次之后,就不再记录
- for (int i = 1; i < 10; ++i)
- {
- LOG_N_TIMES(6, INFO) << "LOG_N_TIMES i = " << i;
- }
- system("pause");
- return 0;
- }
STL容器日志记录
在前面的文章《日志库EasyLogging++学习系列(5)—— 辅助配置功能》中,已经给过示例演示了如何记录 STL 容器日志的方式。再次提示,使用 STL容器日志记录需要定义宏 ELPP_STL_LOGGING,每个容器默认最大容量是 100。下面是 Easylogging++ 支持的 STL 容器类型:
* * * *
Template Macro Needed
ELPP_LOG_STD_ARRAY
std::unordered_mapELPP_LOG_UNORDERED_MAP
std::unordered_multimapELPP_LOG_UNORDERED_MAP
std::unordered_setELPP_LOG_UNORDERED_SET
std::unordered_multisetELPP_LOG_UNORDERED_SET
系统日志记录
系统日志需要系统具有头文件 syslog.h 的支持,这个头文件在 Linux 系统下才有,也就是说Windows 系统是不支持 Easylogging++ 的系统日志功能的。因为我并没有在 linux下用过 Easylogging++,在这里只简单介绍一下。如果想要使用系统日志功能,必须先定义宏ELPP_SYSLOG 的,系统日志默认使用 ID 为 “syslog” 的日志记录器,可以用以下的宏记录日志:
- SYSLOG(LEVEL)
- SYSLOG_IF(Condition, LEVEL)
- SYSLOG_EVERY_N(n, LEVEL)
- CSYSLOG(LEVEL, loggerId)
- CSYSLOG_IF(Condition, LEVEL, loggerId)
- CSYSLOG_EVERY_N(n, LEVEL, loggerId)
- INFO (LOG_INFO)
- DEBUG (LOG_DEBUG)
- WARNING (LOG_WARNING)
- ERROR (LOG_ERR)
- FATAL (LOG_EMERG)
CHECK(condition)
Checks for condition e.g, CHECK(isLoggedIn()) << "Not logged in";
CHECK_EQ(a, b)
Equality check e.g, CHECK_EQ(getId(), getLoggedOnId()) << "Invalid user logged in";
CHECK_NE(a, b)
Inequality check e.g, CHECK_NE(isUserBlocked(userId), false) << "User is blocked";
CHECK_LT(a, b)
Less than e.g, CHECK_LT(1, 2) << "How 1 is not less than 2";
CHECK_GT(a, b)
Greater than e.g, CHECK_GT(2, 1) << "How 2 is not greater than 1?";
CHECK_LE(a, b)
Less than or equal e.g, CHECK_LE(1, 1) << "1 is not equal or less than 1";
CHECK_GE(a, b)
Greater than or equal e.g, CHECK_GE(1, 1) << "1 is not equal or greater than 1";
CHECK_NOTNULL(pointer)
Ensures pointer is not null - if OK returns pointer e.g, explicit MyClass(Obj* obj) : m_obj(CHECK_NOT_NULL(obj)) {}
CHECK_STREQ(str1, str2)
C-string equality (case-sensitive) e.g, CHECK_STREQ(argv[1], "0") << "First arg cannot be 0";
CHECK_STRNE(str1, str2)
C-string inequality (case-sensitive) e.g, CHECK_STRNE(username1, username2) << "Usernames cannot be same";
CHECK_STRCASEEQ(str1, str2)
C-string inequality (case-insensitive) e.g, CHECK_CASESTREQ(argv[1], "Z") << "First arg cannot be 'z' or 'Z'";
CHECK_STRCASENE(str1, str2)
C-string inequality (case-insensitive) e.g,CHECK_STRCASENE(username1, username2) << "Same username not allowed";
CHECK_BOUNDS(val, min, max)
Checks that val
falls under the min
and max
range e.g,CHECK_BOUNDS(i, 0, list.size() - 1) << "Index out of bounds";
详细的用法请看演示代码,需要特别注意的是宏 CHECK_NOTNULL(pointer) 的用法:- #include "easylogging++.h"
- INITIALIZE_EASYLOGGINGPP
- int main(void)
- {
- el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);
- /// CHECK(condition)
- CHECK(1 < 2) << "CHECK(condition) example 1"; // condition为真时不记录
- CHECK(1 > 2) << "CHECK(condition) example 2"; // condition为假时才记录
- /// CHECK_EQ(a, b)
- CHECK_EQ(1, 1) << "CHECK_EQ(a, b) example 1"; // 满足a = b时不记录
- CHECK_EQ(1, 0) << "CHECK_EQ(a, b) example 3"; // 不满足a = b时记录
- /// CHECK_NE(a, b)
- CHECK_NE(1, 2) << "CHECK_NE(a, b) example 1"; // 满足a != b 时不记录
- CHECK_NE(1, 1) << "CHECK_NE(a, b) example 2"; // 不满足a != b 时记录
- /// CHECK_LT(a, b)
- CHECK_LT(1, 2) << "CHECK_LT(a, b) example 1"; // 满足a < b时不记录
- CHECK_LT(1, 1) << "CHECK_LT(a, b) example 2"; // 不满足a < b时记录
- /// CHECK_GT(a, b)
- CHECK_GT(2, 1) << "CHECK_GT(a, b) example 1"; // 满足a > b时不记录
- CHECK_GT(1, 1) << "CHECK_GT(a, b) example 2"; // 不满足a > b时记录
- /// CHECK_LE(a, b)
- CHECK_LE(1, 1) << "CHECK_LE(a, b) example 1"; // 满足a <= b时不记录
- CHECK_LE(1, 0) << "CHECK_LE(a, b) example 2"; // 不满足a <= b时记录
- /// CHECK_GE(a, b)
- CHECK_GE(1, 1) << "CHECK_GE(a, b) example 1"; // 满足a >= b时不记录
- CHECK_GE(1, 2) << "CHECK_GE(a, b) example 2"; // 不满足a >= b时记录
- /// CHECK_STREQ(str1, str2) C风格字符串区分大小写
- CHECK_STREQ("abc", "abc") << "CHECK_STREQ(str1, str2) example 1"; // 满足str1 = str2时不记录
- CHECK_STREQ("abc", "ABC") << "CHECK_STREQ(str1, str2) example 2"; // 不满足str1 = str2时记录
- /// CHECK_STRNE(str1, str2) C风格字符串区分大小写
- CHECK_STRNE("abc", "ABC") << "CHECK_STRNE(str1, str2) example 1"; // 满足str1 != str2时不记录
- CHECK_STRNE("abc", "abc") << "CHECK_STRNE(str1, str2) example 2"; // 不满足str1 != str2时记录
- /// CHECK_STRCASEEQ(str1, str2) C风格字符串不区分大小写
- CHECK_STRCASEEQ("abc", "ABC") << "CHECK_STRCASEEQ(str1, str2) example 1"; // 满足str1 = str2时不记录
- CHECK_STRCASEEQ("abc", "abd") << "CHECK_STRCASEEQ(str1, str2) example 2"; // 不满足str1 = str2时记录
- /// CHECK_STRCASENE(str1, str2) C风格字符串不区分大小写
- CHECK_STRCASENE("abc", "abd") << "CHECK_STRCASENE(str1, str2) example 1"; // 满足str1 != str2时不记录
- CHECK_STRCASENE("abc", "ABC") << "CHECK_STRCASENE(str1, str2) example 2"; // 不满足str1 != str2时记录
- /// CHECK_NOTNULL(pointer) 判断指针pointer是否为空,不为空时返回pointer
- int* f = nullptr;
- if (CHECK_NOTNULL(f))
- {
- }
- f = new int;
- if (CHECK_NOTNULL(f))
- {
- }
- delete f;
- f = nullptr;
- int min = 2;
- int max = 5;
- CHECK_BOUNDS(1, min, max) << "CHECK_BOUNDS(val, min, max) example 1";
- CHECK_BOUNDS(2, min, max) << "CHECK_BOUNDS(val, min, max) example 2";
- CHECK_BOUNDS(3, min, max) << "CHECK_BOUNDS(val, min, max) example 3";
- CHECK_BOUNDS(4, min, max) << "CHECK_BOUNDS(val, min, max) example 4";
- CHECK_BOUNDS(5, min, max) << "CHECK_BOUNDS(val, min, max) example 5";
- CHECK_BOUNDS(6, min, max) << "CHECK_BOUNDS(val, min, max) example 6";
- system("pause");
- return 0;
- }
- info(const char*, const T&, const Args&...)
- warn(const char*, const T&, const Args&...)
- error(const char*, const T&, const Args&...)
- debug(const char*, const T&, const Args&...)
- fatal(const char*, const T&, const Args&...)
- trace(const char*, const T&, const Args&...)
- verbose(int vlevel, const char*, const T&, const Args&...)
- #define ELPP_STL_LOGGING
- #include "easylogging++.h"
- INITIALIZE_EASYLOGGINGPP
- int main(int argc, char** argv)
- {
- el::Logger* defaultLogger = el::Loggers::getLogger("default");
- std::vector<int> i;
- i.push_back(1);
- i.push_back(2);
- /// 记录STL容器数据
- defaultLogger->warn("My first ultimate log message %v %v %v", 123, 222, i);
- // 利用转义字符输出 % 和 %v
- defaultLogger->info("My first ultimate log message %% %%v %v %v", 123, 222);
- system("pause");
- return 0;
- }
在C语言库函数中有个errno变量,每个errno值对应着以字符串表示的错误类型。当你调用某些库函数出错时,被调用的函数会重新设置了errno的值,而 perror() 函数就是用于将你输入的一些信息和现在的errno所对应的错误一起输出。在 Easylogging++ 中,也支持在作用上类似 perror() 函数的宏定义:
PLOG(LEVEL)
PLOG_IF(Condition,
LEVEL)PCHECK()
CPLOG(LEVEL, LoggerId)
CPLOG_IF(Condition, LEVEL, LoggerId)
下面的代码演示了 perror 风格日志记录的使用方式:
- #include "easylogging++.h"
- INITIALIZE_EASYLOGGINGPP
- int main(void)
- {
- el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);
- /// 读取一个不存在的文件,改变errno变量的值
- std::fstream f("a file that does not exist", std::ifstream::in);
- /// PLOG(LEVEL)
- PLOG(INFO) << "A message with plog";
- /// PLOG_IF(Condition, LEVEL), 条件为真时才记录
- PLOG_IF(true, INFO) << "A message with plog 1";
- PLOG_IF(false, INFO) << "A message with plog 2";
- /// PCHECK() 满足条件不记录,不满足才记录
- PCHECK(true) << "check message with plog 1";
- PCHECK(false) << "check message with plog 2";
- system("pause");
- return 0;
- }
DEBUG模式日志记录
在前面的文章《日志库EasyLogging++学习系列(2)—— 日志级别》中,简单地提到了DEBUG模式的日志记录。所谓的DEBUG模式,就是只在Debug版本的程序中才有意义,而在Release版本的程序中则没有意义。在本文以上内容所提到的全部的日志记录方式中,只要是以宏定义形式记录日志信息的,基本上都会有一个DEBUG模式对应的宏定义。在 Easylogging++ 中,所有用于DEBUG模式的宏定义都是以大写字母 D 开头的,由于DEBUG模式宏定义的使用方式和常规的宏定义使用方式都是一样的,这里不再赘述,建议有兴趣了解更多关于DEBUG模式日志详细信息的小伙伴可以亲自动手试一试。
- 日志库EasyLogging++学习系列(7)—— 记录方式详解
- 日志库EasyLogging++学习系列(7)—— 记录方式详解
- 日志库EasyLogging++学习系列(8)—— Verbose日志详解
- 日志库EasyLogging++学习系列(8)—— Verbose日志详解
- 日志库EasyLogging++学习系列(11)—— 共享日志库
- 日志库EasyLogging++学习系列(11)—— 共享日志库
- 日志库EasyLogging++学习系列(2)—— 日志级别
- 日志库EasyLogging++学习系列(6)—— 日志记录器
- 日志库EasyLogging++学习系列(10)—— 日志文件滚动
- 日志库EasyLogging++学习系列(2)—— 日志级别
- 日志库EasyLogging++学习系列(6)—— 日志记录器
- 日志库EasyLogging++学习系列(10)—— 日志文件滚动
- 日志库EasyLogging++学习系列(1)—— 简要介绍
- 日志库EasyLogging++学习系列(3)—— 配置功能
- 日志库EasyLogging++学习系列(4)—— 格式说明符
- 日志库EasyLogging++学习系列(5)—— 辅助配置功能
- 日志库EasyLogging++学习系列(9)—— 性能跟踪功能
- 日志库EasyLogging++学习系列(1)—— 简要介绍
- iOS 设置某个ViewController可以旋转
- 关于java类继承特性的一些认识
- 远程通信机制RPC与RMI的关系
- Vue2接口地址配置(webpack)
- 【Jquery学习】第六部分
- 日志库EasyLogging++学习系列(7)—— 记录方式详解
- validator手机验证
- java日志文件log4j.properties配置详解
- Android控件架构
- go 接口
- Dalvik与ART的介绍及区别(一)
- 日志库EasyLogging++学习系列(8)—— Verbose日志详解
- dubbo通信协议之对比
- 2015级+ 计算机3班+张毅+海马汽车经销商管理系统项目实训技术总结