正如前面《 日志库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 to NewLineForContainer 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++ 支持的日志标记:

FlagDescription
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 NameDescription
ELPP_DEBUG_ASSERT_FAILUREAborts application on first assertion failure. This assertion is due to invalid input e.g, invalid configuration file etc.
ELPP_UNICODEEnables Unicode support when logging. RequiresSTART_EASYLOGGINGPP
ELPP_THREAD_SAFEEnables thread-safety - make sure -lpthread linking for Linux.
ELPP_FORCE_USE_STD_THREADForces to use C++ standard library for threading (Only useful when using ELPP_THREAD_SAFE
ELPP_STACKTRACE_ON_CRASHApplicable to GCC only. Enables stacktrace on application crash
ELPP_DISABLE_DEFAULT_CRASH_HANDLINGDisables default crash handling. You can use el::Helpers::setCrashHandler to use your own handler.
ELPP_DISABLE_LOGSDisables all logs - (preprocessing)
ELPP_DISABLE_DEBUG_LOGSDisables debug logs - (preprocessing)
ELPP_DISABLE_INFO_LOGSDisables info logs - (preprocessing)
ELPP_DISABLE_WARNING_LOGSDisables warning logs - (preprocessing)
ELPP_DISABLE_ERROR_LOGSDisables error logs - (preprocessing)
ELPP_DISABLE_FATAL_LOGSDisables fatal logs - (preprocessing)
ELPP_DISABLE_VERBOSE_LOGSDisables verbose logs - (preprocessing)
ELPP_DISABLE_TRACE_LOGSDisables trace logs - (preprocessing)
ELPP_FORCE_ENV_VAR_FROM_BASHIf 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_FILEFull 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_FILEIf 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_ERRORSIf 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_SPECIFIERSForcefully disables custom format specifiers
ELPP_DISABLE_LOGGING_FLAGS_FROM_ARGForcefully disables ability to set logging flags using command-line arguments
ELPP_DISABLE_LOG_FILE_FROM_ARGForcefully disables ability to set default log file from command-line arguments
ELPP_WINSOCK2On 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;
                        原文链接:https://blog.csdn.net/Qsir/article/details/73335870?ops_request_misc=%25257B%252522request%25255Fid%252522%25253A%252522160994615616780262537540%252522%25252C%252522scm%252522%25253A%25252220140713.130102334.pc%25255Fall.%252522%25257D&request_id=16099461
                                    在编译程序并运行后,Delphi2007会提示以下错误(windows 7 64位 运行环境):
---------------------------
bds.exe - bordbk105N.dll
---------------------------
Assertion failure: "(!"SetThreadContext failed")"
in ..\win32src\
                                    通常是因为我们定义的Servlet名少了个/,还有一种原因是因为我们的Servlet同名了。这个问题是因为我们在我们启动Tomcat时Server发生错误。Assertion failure报错解决方案。
在 easylogging++的 功能介绍 中我们简要介绍过崩溃处理相关的内容。
easylogging++中崩溃处理相关的主要有两块: 1) 系统信号处理器 2) 堆栈跟踪( 仅仅支持 GCC )
基本用法如下,引用头文件,添加初始化宏,配置log的文件名,配置Log的格式,再写入log
写入log的时候,可以使用LOG(INFO) <<这样的格式,也可以使用printf类的格式,但是要注意:
printf格式只能用%v,不能使用%s, %d这些。否则此条日志不会有任何输出。
  LOG(INFO) << "Here is very simple example.";  
#include "easylogging++.h"
INITIALIZE_EA.
                                    Easylogging++的优势是它的速度和简单。 它是轻量级的,健壮的,高性能,线程和类型安全的,它有许多内置功能。它适合在中小型项目中使用,它提供了自定义日志格式的能力,还提供对第三方,STL容器的支持。
示例代码:
                                    Easylogging++ 一共只有两个文件,一个是头文件,一个是普通 C++ 源文件。事实上,它的一个较早版本只有一个文件。正如 Catch2 里一旦定义了编译速度会大大减慢一样,把什么东西都放一起最终证明对编译速度还是相当不利的,因此,有人提交了一个补丁,把代码拆成了两个文件。使用 Easylogging++ 也只需要这两个文件——除此之外,就只有对标准和系统头文件的依赖了。要使用 Easylogging++,推荐直接把这两个文件放到你的项目里。
el::Configurations conf;
//el::Configurations conf("E:\\github\\c-\\faceDetect\\Release\\log.conf");
//el::Configurations conf("log.conf");
//el::Loggers::rec...
                                    easylogging++对于日志格式的管理主要是通过两个类来实现的: Configurations 类和 TypedConfigurations 类。在 easylogging++的总体设计中简单介绍过这两个类的用途:  
Configurations类主要用于以字符串形式保存配置项的值。TypedConfigurations 类主要用于以配置项在程序运行时的实际类型保存配置项的值。