日志库EasyLogging++学习系列(5)—— 辅助配置功能

正如前面《日志库EasyLogging++学习系列(3)—— 配置功能》文中最后提到的,在某些应用场景下,我们还需要通过其他的一些配置手段来辅助我们完成某些特殊功能,这些辅助配置手段包括设置命令行参数、设置日志标记、配置宏定义。本文中就对这几个辅助配置功能逐一进行简要介绍。


命令行参数


在 Easylogging++ 中可以通过START_EASYLOGGINGPP(argc, argv) 来完成命令行参数的设置,下面的表格列举了GitHub上给出的 Easylogging++ 支持的命令行参数:


Argument Description
-v Activates maximum verbosity
--v=2 Activates verbosity upto verbose level 2 (valid range: 0-9)
--verbose Activates maximum verbosity
-vmodule=MODULE_NAME Activates verbosity for files starting with main to level 1, the rest of the files depend on logging flag AllowVerboseIfModuleNotSpecified Please see Logging Flags section above. Two modules can be separated by comma. Please note vmodules are last in order of precedence of checking arguments for verbose logging, e.g, if we have -v in application arguments before vmodules, vmodules will be ignored.
--logging-flags=3 Sets logging flag. In example i.e, 3, it sets logging flag toNewLineForContainer and AllowVerboseIfModuleNotSpecified. See logging flags section above for further details and values. See macros section to disable this function.
--default-log-file=FILE Sets default log file for existing and future loggers. You may want to consider defining ELPP_NO_DEFAULT_LOG_FILE to prevent creation of default empty log file during pre-processing. See macros section to disable this function.
对于上述命令行参数,有必要简单说明一下:

  • 其中的 -v 、 --v 、 --verbose 、 -vmodule 都是用来设置 Verbose 详细日志的,而且这几个参数之间是有优先级顺序的,如下:-v  优先于 --verbose 优先于 --v 优先于 -vmodule。但是,在效果上 -v 和 --verbose 是一样的。请看下面的例子:

命令行参数例一:--v=2 -v ,在这里参数 --v=2 会被参数 -v 覆盖,因为 -v 优先级最高。

命令行参数例二:--verbose -vmodule=main=3 ,在这里参数 -vmodule=main=3 会被参数 --verbose 覆盖,因为 --verbose 优先于 -vmodule 。

命令行参数例三:-vmodule=main*=3 --v=5 -v --verbose ,在这里参数 -v 会覆盖其他所有的参数,因为 -v 优先级最高。

  • 其中的 --logging-flags 是用来设置日志标记的,而且必须定义 ELPP_LOGGING_FLAGS_FROM_ARG 这个宏定义。
  • 其中的 --default-log-file 是用来设置日志默认保存文件名的。如果没用这个命令行参数设置文件名,那么默认的文件名就是 logs\\myeasylog.log 。另外,我们也可以用宏定义 ELPP_DEFAULT_LOG_FILE 来达到相同的效果。如:#defineELPP_DEFAULT_LOG_FILE "logs\\tem\\test.log" 。
下面的代码演示了设置命令行参数 --v=2 ,其最终效果是 VLOG(3) 将会被屏蔽:
#include "easylogging++.h"

INITIALIZE_EASYLOGGINGPP

int main(int argc, char** argv)
{
	/// 请自行加上命令行参数 --v=2,否则达不到演示的效果
	START_EASYLOGGINGPP(argc, argv);

	VLOG(0);
	VLOG(1);
	VLOG(2);
	VLOG(3);

	system("pause");
	return 0;
}
更多关于Verbose日志的详细信息请参考《 日志库EasyLogging++学习系列(8)—— Verbose日志详解 》。


日志标记


在学习日志标记之前,我们先来看看 Easylogging++ 提供出来的三个和日志标记紧密相关的功能接口函数:

  • 增加标记函数: el::Loggers::addFlag 
  • 删除标记函数:el::Loggers::removeFlag 
  • 检查标记函数:el::Loggers::hasFlag 

下面的表格列举了GitHub上给出的 Easylogging++ 支持的日志标记:


Flag Description
NewLineForContainer (1) Makes sure we have new line for each container log entry
AllowVerboseIfModuleNotSpecified (2) Makes sure if -vmodule is used and does not specifies a module, then verbose logging is allowed via that module. Say param was -vmodule=main*=3 and a verbose log is being written from a file called something.cpp then if this flag is enabled, log will be written otherwise it will be disallowed. Note: having this defeats purpose of -vmodule
LogDetailedCrashReason (4) When handling crashes by default, detailed crash reason will be logged as well (Disabled by default) (issue #90)
DisableApplicationAbortOnFatalLog (8) Allows to disable application abortion when logged using FATAL level. Note that this does not apply to default crash handlers as application should be aborted after crash signal is handled. (Not added by default) (issue #119)
ImmediateFlush (16) Flushes log with every log-entry (performance sensative) - Disabled by default
StrictLogFileSizeCheck (32) Makes sure log file size is checked with every log
ColoredTerminalOutput (64) Terminal output will be colorful if supported by terminal.
MultiLoggerSupport (128) Enables support for using multiple loggers to log single message. (E.g, CLOG(INFO, "default", "network") << This will be logged using default and network loggers;)
DisablePerformanceTrackingCheckpointComparison (256) Disables checkpoint comparison
DisableVModules (512) Disables usage of vmodules
DisableVModulesExtensions (1024) Disables vmodules extension. This means if you have a vmodule -vmodule=main*=4 it will cover everything starting with main, where as if you do not have this defined you will be covered for any file starting with main and ending with one of the following extensions; .h .c .cpp .cc .cxx .-inl-.h .hxx .hpp. Please note following vmodule is not correct -vmodule=main.=4 with this macro not defined because this will check for main..c, notice double dots. If you want this to be valid, have a look at logging flag above: AllowVerboseIfModuleNotSpecified '?' and '' wildcards are supported
HierarchicalLogging (2048) Enables hierarchical logging. This is not applicable to verbose logging.
CreateLoggerAutomatically (4096) Creates logger automatically when not available.
AutoSpacing (8192) Automatically adds spaces. E.g,LOG(INFO) << "DODGE" << "THIS!"; will output "DODGE THIS!"
FixedTimeFormat (16384) Applicable to performace tracking only - this prevents formatting time. E.g, 1001 ms will be logged as is, instead of formatting it as 1.01 sec
对于上述的日志标记,可在 Easylogging++ 源码中查看枚举值el::LoggingFlag ,每个标记的含义在表格和源码中都描述得比较清楚了,不过还是建议大家都亲自动手试一试,下面的代码演示了标记 NewLineForContainer 的作用:

#define ELPP_STL_LOGGING
#include "easylogging++.h"

INITIALIZE_EASYLOGGINGPP

int main(int argc, char** argv)
{
	std::vector<int> vecNum;
	vecNum.push_back(1);
	vecNum.push_back(2);
	vecNum.push_back(3);

	/// 增加标记 NewLineForContainer,注意查看输出STL容器的效果
	el::Loggers::addFlag(el::LoggingFlag::NewLineForContainer);
	LOG(INFO) << vecNum;

	/// 删除标记 NewLineForContainer,注意查看输出STL容器的效果
	el::Loggers::removeFlag(el::LoggingFlag::NewLineForContainer);
	LOG(INFO) << vecNum;
	
	system("pause");
	return 0;
}

配置宏定义


在 Easylogging++ 中,有些功能必须定义相应的宏定义才能开启。为了方便记忆,Easylogging++ 中所有的宏定义都是以 ELPP_ 开头的,所以可以在源码中搜索 ELPP_ 来查看都定义了哪些宏定义。下面的表格列举了GitHub上给出的 Easylogging++ 支持的宏定义(只列举了部分):


Macro Name Description
ELPP_DEBUG_ASSERT_FAILURE Aborts application on first assertion failure. This assertion is due to invalid input e.g, invalid configuration file etc.
ELPP_UNICODE Enables Unicode support when logging. RequiresSTART_EASYLOGGINGPP
ELPP_THREAD_SAFE Enables thread-safety - make sure -lpthread linking for linux.
ELPP_FORCE_USE_STD_THREAD Forces to use C++ standard library for threading (Only useful when using ELPP_THREAD_SAFE
ELPP_STACKTRACE_ON_CRASH Applicable to GCC only. Enables stacktrace on application crash
ELPP_DISABLE_DEFAULT_CRASH_HANDLING Disables default crash handling. You can use el::Helpers::setCrashHandler to use your own handler.
ELPP_DISABLE_LOGS Disables all logs - (preprocessing)
ELPP_DISABLE_DEBUG_LOGS Disables debug logs - (preprocessing)
ELPP_DISABLE_INFO_LOGS Disables info logs - (preprocessing)
ELPP_DISABLE_WARNING_LOGS Disables warning logs - (preprocessing)
ELPP_DISABLE_ERROR_LOGS Disables error logs - (preprocessing)
ELPP_DISABLE_FATAL_LOGS Disables fatal logs - (preprocessing)
ELPP_DISABLE_VERBOSE_LOGS Disables verbose logs - (preprocessing)
ELPP_DISABLE_TRACE_LOGS Disables trace logs - (preprocessing)
ELPP_FORCE_ENV_VAR_FROM_BASH If environment variable could not be found, force using alternative bash command to find value, e.g,whoami for username. (DO NOT USE THIS MACRO WITH LD_PRELOAD FOR LIBRARIES THAT ARE ALREADY USING Easylogging++ OR YOU WILL END UP IN STACK OVERFLOW FOR PROCESSES (popen) (see issue #87 for details))
ELPP_DEFAULT_LOG_FILE Full filename where you want initial files to be created. You need to embed value of this macro with quotes, e.g, -DELPP_DEFAULT_LOG_FILE='"logs/el.gtest.log"'Note the double quotes inside single quotes, double quotes are the values for const char* and single quotes specifies value of macro
ELPP_NO_DEFAULT_LOG_FILE If you dont want to initialize library with default log file, define this macro. But be sure to configure your logger with propery log filename or you will end up getting heaps of errors when trying to log to file (andTO_FILE is configured to true)
ELPP_DEBUG_ERRORS If you wish to find out internal errors raised by Easylogging++ that can be because of configuration or something else, you can enable them by defining this macro. You will get your errors on standard output i.e, terminal or command prompt.
ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS Forcefully disables custom format specifiers
ELPP_DISABLE_LOGGING_FLAGS_FROM_ARG Forcefully disables ability to set logging flags using command-line arguments
ELPP_DISABLE_LOG_FILE_FROM_ARG Forcefully disables ability to set default log file from command-line arguments
ELPP_WINSOCK2 On windows system force to use winsock2.hinstead of winsock.h when WIN32_LEAN_AND_MEANis defined

利用在上述的宏定义,可以完成一些配置文件中无法完成的配置。下面简单介绍几个比较实用的宏定义:

  • ELPP_DEBUG_ASSERT_FAILURE 宏定义,可以帮助我们检测配置文件中的配置项名称是否正确,假如配置项名称不是Easylogging++ 支持的,那么就会出现断言中断。
  • ELPP_UNICODE 宏定义,默认的日志记录是只支持多字节字符串的,同时使用这个宏定义和 START_EASYLOGGINGPP(argc, argv) 可以开启 Unicode 字符串记录日志的功能。
  • ELPP_THREAD_SAFE 宏定义,在默认情况下,考虑到性能,多线程安全功能是关闭的,使用这个宏定义则可以开启。
  • ELPP_STL_LOGGING 宏定义,使 Easylogging++ 支持STL模板和容器类型的日志输出,比如上面第二部分介绍日志标记最后给出例子。考虑到性能,每个容器最大容量是 100,可以通过修改源码改变这个限制,但不建议这么做,除非你可以无视性能和效率。
当然,其他的宏定义也很实用,建议大家也可以亲自试一试,看看其实际的作用。需要注意的是,有些宏必须在包含 Easylogging++ 头文件之前,即必须在代码 #include "easylogging++.h" 之前完成定义才有意义。下面的代码演示了宏定义 ELPP_UNICODE 的作用:
#define ELPP_UNICODE
#include "easylogging++.h"

INITIALIZE_EASYLOGGINGPP

int main(int argc, char** argv)
{
	/// 同时使用 START_EASYLOGGINGPP 才能使用Unicode 
	START_EASYLOGGINGPP(argc, argv);

	LOG(INFO) << L"宏定义演示。";

	system("pause");
	return 0;
}


你可能感兴趣的:(日志库EasyLogging++学习系列(5)—— 辅助配置功能)