这里之所以把Verbose日志单独拿出来讲,是因为最初接触 Easylogging++ 的时候,对Verbose级别的日志感到有点迷惑,并不是十分清楚其用法。不过后来发现,在不扩展日志级别的情况下,其实Verbose日志可以让我们更轻松地记录更多更详细的信息,特别是在排错的日志记录中,没有哪个级别的日志比使用Verbose级别的日志更为合适了。

 

正如如前面文章提到的一样,Verbose日志并不适用于划分级别的日志记录,意思就是说在设置了标记:LoggingFlag::HierarchicalLogging 的日志记录中,即使门阀值设置大于Verbose级别,甚至是设置成Unknown,也无法关闭Verbose级别日志的输出。同时,Verbose日志拥有专属的宏定义来记录日志,而不支持类似于 LOG(VERBOSE) 等宏定义。下面列出Verbose日志专属的宏定义:

 

  • VLOG(verbose-level)
  • CVLOG(verbose-level, logger ID)
  • VLOG_IF(condition, verbose-level)
  • CVLOG_IF(condition, verbose-level, loggerID)
  • VLOG_EVERY_N(n, verbose-level)
  • CVLOG_EVERY_N(n, verbose-level, loggerID)
  • VLOG_AFTER_N(n, verbose-level)
  • CVLOG_AFTER_N(n, verbose-level, loggerID)
  • VLOG_N_TIMES(n, verbose-level)
  • CVLOG_N_TIMES(n, verbose-level, loggerID)

提示:Verbose日志同样支持DEBUG模式,上述所有宏定义都有与之对应的DEBUG模式的宏定义,在前面加上大写字母 D 即可。

 

 

理解Verbose日志的级别

 

Verbose日志可以分为 1 ~ 9 共九个级别,而这九个级别最初是处于未激活状态的。所谓的未激活状态就是说在默认的情况下,这九个级别的Verbose日志是不会输出日志信息的,除非我们设置程序参数来激活它。而VLOG(0)虽然也可以记录Verbose日志,但是它在默认的情况下是可以输出日志信息的,所以 0 并不属于Verbose日志的级别。不过实践发现,即使把 0 理解成Verbose日志的级别也可以,即可以认为Verbose日志分为 0 ~ 9 共十个级别,只是 0 级别的日志是无法被禁止输出的而已,但是在vmodule分模块日志部分内容演示代码中有一种方法可以把 VLOG(0) 的输出也禁用了。

 

 

设置Verbose日志的级别

 

在前面《日志库EasyLogging++学习系列(5)—— 辅助配置功能》这篇文章中,其实已经演示了一种设置Verbose日志级别的方法,即通过命令行参数来设置。在命令行参数中, -v 、 --verbose 、--v 、 -vmodule 都是用来设置Verbose日志的,这四个参数只能有一个生效,优先级高的会覆盖优先级低的(优先级: -v   >  --verbose  >  --v  >  -vmodule )。但是,在效果上 -v 和 --verbose 是一样的。在这里介绍另外一种可以动态设置Verbose日志级别的方法,就是利用函数 Loggers::setVerboseLevel(base::type::VerboseLevel) 来设置,其中的 base::type::VerboseLevel 实际上是个 int 整型。不过需要特别注意的是,该函数不适应于 -vmodule。关于 -vmodule 的级别设置请参考本文中下面的vmodule分模块日志部分内容。

 

 

判断Verbose日志的级别

 

我们可以通过函数 Loggers::verboseLevel() 来获取当前Verbose日志的级别,也可以利用宏 VLOG_IS_ON(verbose-level) 来判断某个级别是否已被激活。下面的代码演示了设置和判断Verbose日志级别的用法:

[cpp] view plain copy

1. #include "easylogging++.h"  
2.   
3. INITIALIZE_EASYLOGGINGPP  
4.   
5. int main(int argc, char** argv)  
6. {  
7. int verboseLevel = 0;  
8. /// 获取Verbose日志级别  
9.     verboseLevel = el::Loggers::verboseLevel();  
10. "Verbose Level = " << verboseLevel;  
11.   
12.     VLOG(0);  
13. //该行不会输出  
14.   
15. /// 动态设置Verbose日志级别  
16.     el::Loggers::setVerboseLevel(3);  
17. /// 获取Verbose日志级别  
18.     verboseLevel = el::Loggers::verboseLevel();  
19. "Verbose Level = " << verboseLevel;  
20.       
21.     VLOG(1);  
22.     VLOG(2);  
23.     VLOG(3);  
24. //该行不会输出  
25.   
26. /// 动态设置Verbose日志级别  
27.     el::Loggers::setVerboseLevel(9);  
28. /// 获取Verbose日志级别  
29.     verboseLevel = el::Loggers::verboseLevel();  
30. "Verbose Level = " << verboseLevel;  
31.   
32.     VLOG(4);  
33.     VLOG(5);  
34.     VLOG(6);  
35.     VLOG(7);  
36.     VLOG(8);  
37.     VLOG(9);  
38. //该行不会输出  
39.   
40. /// 尝试将Verbose日志级别设置为10  
41.     el::Loggers::setVerboseLevel(10);  
42. /// 获取Verbose日志级别  
43.     verboseLevel = el::Loggers::verboseLevel();  
44. "Verbose Level = " << verboseLevel;  
45.   
46. //该行不会输出  
47.   
48. "pause");  
49. return 0;  
50. }


vmodule分模块日志

 

分模块日志也可以叫分文件日志,如果以前接触过GLOG日志库的小伙伴会对这个概念比较好理解,因为GLOG日志库也有这个功能。简单来说,分模块日志就是可以指定哪些文件中的日志允许输出,哪些文件中的日志不允许输出。因为分模块日志本身就是Verbose日志,所以在指定文件的同时,还必须指定Verbose日志的级别,而 -vmodule 就是用来指定文件和级别的,必须遵循下面的格式:

-vmodule=<module name>=<verboser level>,<module name>=<verboser level>,···

在格式中,多个模块之间用英文逗号“,”隔开;而<verbose level>表示Verbose日志的级别,<module name>则表示文件的名称,文件名称中支持通配符“*”和“?”。在默认情况下,Easylogging++ 会自动在文件名称后加上文件扩展名(.h, .c, .cpp, .cc, .cxx, -inl.h, .hxx, .hpp),请看下面的例子:

  • 命令行参数 -vmodule=main=3 ,表示只有以下所列文件会输出日志,并且只能输出Verbose级别不大于 3 的日志。

main.h、main.c、main.cpp、main.cc、main.cxx、main.-inl.h、main.hxx、main.hpp

  • 命令行参数 -vmodule=main=5,parse*=6 ,表示名称为 main 的文件能够输出Verbose级别不大于 5 的日志,而名称为 parse* 的文件能够输出Verbose级别不大于 6 的日志(注意 main 文件 和 parse* 文件会自动加上文件扩展名)。

但是如果设置了标记:LoggingFlag::DisableVModulesExtensions,那么<module name>表示的文件名称就不会在后面加上扩展名了。另外还有一个与 Verbose 日志相关的标记 LoggingFlag::AllowVerboseIfModuleNotSpecified ,如果设置了该标记并且使用 -vmodule 来指定文件和级别,那么除了指定的文件会按照指定的Verbose级别输出日志之外,其他所有的文件中全部的 Verbose 日志都会输出。当我们在初始化日志库的宏定义中就已经默认设置了标记 LoggingFlag::AllowVerboseIfModuleNotSpecified ,这一点需要特别注意,所以如果希望在程序中使用 -vmodule 来指定文件和级别控制日志输出,必须先用 el::Loggers::removeFlag 将标记 LoggingFlag::AllowVerboseIfModuleNotSpecified 删除才行,否则可能达不到预期的效果。最后,还有一个比较有用的标记LoggingFlag::DisableVModules ,这个标记可以用来完全关闭 vmodule 分模块日志。

 

除了可以用命令行参数设置 vmodule 分模块日志之外,还可以利用函数 Loggers::setVModules(const char*) 来动态设置,只是函数中的参数就不需要用“-vmodule=<module name>=<verboser level>”的格式了,只需直接指定文件名和级别就行了。比如直接传入参数“main=3”就行了。需要注意的是,除了第一次调用函数 Loggers::setVModules(const char*) 之外,如果其他的地方想要再次调用该函数来实现动态设置,都必须先调用 Loggers::clearVModules() 来清除之前设置过的参数,否则,后面设置的参数都将无法覆盖第一次设置的参数。下面给出关于分模块日志的部分功能的演示代码:

[cpp] view plain copy

 

    1. #include "easylogging++.h"  
    2.   
    3. INITIALIZE_EASYLOGGINGPP  
    4.   
    5. int main(int argc, char** argv)  
    6. {  
    7.     VLOG(0);  
    8.   
    9. /// 特别注意这里的参数"*main=3",如果传入"main=3",将达不到预期的效果  
    10. "*main=3");  
    11.       
    12.     VLOG(1);  
    13.     VLOG(2);  
    14.     VLOG(3);  
    15. //这一行不会输出  
    16.   
    17. /// 一定要先clear,否则重新设置参数不生效  
    18.     el::Loggers::clearVModules();  
    19. "*main=6");  
    20.     VLOG(4);  
    21.     VLOG(5);  
    22.     VLOG(6);  
    23. //这一行不会输出  
    24.   
    25. /// 一定要先clear,否则重新设置参数不生效  
    26.     el::Loggers::clearVModules();  
    27. "main=6");  
    28.     VLOG(7);  
    29.     VLOG(8);  
    30.     VLOG(9);  
    31.   
    32. /// 取消标记AllowVerboseIfModuleNotSpecified  
    33.     el::Loggers::removeFlag(el::LoggingFlag::AllowVerboseIfModuleNotSpecified);  
    34.   
    35. /// 以下所有Verbose日志都被禁止输出,包括VLOG(0)  
    36.     VLOG(0);  
    37.     VLOG(1);  
    38.     VLOG(2);  
    39.     VLOG(3);  
    40.     VLOG(4);      
    41.     VLOG(5);  
    42.     VLOG(6);  
    43.     VLOG(7);      
    44.     VLOG(8);      
    45.     VLOG(9);      
    46.   
    47. "pause");  
    48. return 0;  
    49. }

    关于Verbose日志的总结

     

    本文的学习记录中,写了很多关于Verbose日志的功能和用法,其中的内容有些可能比较抽象,特别是vmodule分模块日志,这里只是尽可能详细、简单地进行说明和演示。如果想要更好地理解其中的某些概念,或者功能,还是建议自己真正动手写代码进行尝试和验证,通过编写代码来理解代码绝对是一个很好的学习方法。只有真正地理解了Verbose日志,我们才能将其更好地应用于自己的程序开发当中。

    记录每天生活的点点滴滴,呵呵呵呵呵呵