easylogging++是一个非常轻量级并且非常高效的一个日志库,支持文件配置,支持线程安全,并且其自定义格式非常的方便,最关键的是,其所有代码都集中在一个.h头文件之中,完全不需要引用第三方库,接入时非常的方便。在其github首页上给出了最简单的接入例子:
#include "easylogging++.h" INITIALIZE_EASYLOGGINGPP int main(int argc, char* argv[]) { LOG(INFO) << "My first info log using default logger"; return 0; }
只需要引用一下头文件,并且调用下INITIALIZE_EASYLOGGINGPP宏进行初始化,INITIALIZE_EASYLOGGINGPP紧随着引用头文件之后的位置即可(不能放在头文件中哦),如果不调用这个宏,那么会报出以下错误:
$ g++ test.cpp -o main -std=c++11 /tmp/ccPBiVzm.o: In function `el::base::debug::crashReason(int)': test.cpp:(.text+0x1ed): undefined reference to `el::base::elStorage' /tmp/ccPBiVzm.o: In function `el::base::LogFormat::updateFormatSpec()': test.cpp:(.text._ZN2el4base9LogFormat16updateFormatSpecEv[_ZN2el4base9LogFormat16updateFormatSpecEv]+0xb43): undefined reference to `_ZN2el4base5utils13s_currentUserB5cxx11E' test.cpp:(.text._ZN2el4base9LogFormat16updateFormatSpecEv[_ZN2el4base9LogFormat16updateFormatSpecEv]+0xb85): undefined reference to `_ZN2el4base5utils13s_currentUserB5cxx11E' test.cpp:(.text._ZN2el4base9LogFormat16updateFormatSpecEv[_ZN2el4base9LogFormat16updateFormatSpecEv]+0xc0d): undefined reference to `_ZN2el4base5utils13s_currentHostB5cxx11E' /tmp/ccPBiVzm.o: In function `el::base::LogDispatcher::dispatch()': test.cpp:(.text._ZN2el4base13LogDispatcher8dispatchEv[_ZN2el4base13LogDispatcher8dispatchEv]+0x55): undefined reference to `el::base::elStorage' test.cpp:(.text._ZN2el4base13LogDispatcher8dispatchEv[_ZN2el4base13LogDispatcher8dispatchEv]+0x94): undefined reference to `el::base::elStorage' test.cpp:(.text._ZN2el4base13LogDispatcher8dispatchEv[_ZN2el4base13LogDispatcher8dispatchEv]+0xaf): undefined reference to `el::base::elStorage' test.cpp:(.text._ZN2el4base13LogDispatcher8dispatchEv[_ZN2el4base13LogDispatcher8dispatchEv]+0xfe): undefined reference to `el::base::elStorage' /tmp/ccPBiVzm.o: In function `el::base::MessageBuilder::initialize(el::Logger*)': test.cpp:(.text._ZN2el4base14MessageBuilder10initializeEPNS_6LoggerE[_ZN2el4base14MessageBuilder10initializeEPNS_6LoggerE]+0x1c): undefined reference to `el::base::elStorage' /tmp/ccPBiVzm.o:test.cpp:(.text._ZN2el4base14MessageBuilderlsEm[_ZN2el4base14MessageBuilderlsEm]+0x33): more undefined references to `el::base::elStorage' follow collect2: error: ld returned 1 exit status
我当前使用的easylogger++是v9.80版本,这个版本是需要c++11的支持的。否则无法编译通过。
编译通过之后,运行程序:
$ ./main 2018-06-07 23:34:24,947 INFO [default] My first info log using default logger $ ls easylogging++.h logs main test.cpp $ cd logs/ $ ls myeasylog.log
运行程序之后,发现当前文件夹下多了一个文件夹 logs,进入文件夹logs之后,发现日志内容输入到了myeasylog.log内。
如果想自定义日志文件名字和日志格式,就需要配置自己的配置文件,log.conf:
* GLOBAL: FORMAT = "[%level | %datetime] | %msg" ENABLED = true TO_FILE = true TO_STANDARD_OUTPUT = false PERFORMANCE_TRACKING = false MAX_LOG_FILE_SIZE = 209715200 ## Throw log files away after 2097152 2MB / 209715200 200MB / 4398046511104 1GB * INFO: FILENAME = "log/info_%datetime{%Y%M%d%H}.log" * DEBUG: FILENAME = "log/debug_%datetime{%Y%M%d%H}.log" * WARNING: FILENAME = "log/warn_%datetime{%Y%M%d%H}.log" * TRACE: * VERBOSE: FORMAT = "%level-%vlevel | %datetime{%d/%M/%y} | %msg" * ERROR: FILENAME = "log/error_%datetime{%Y%M%d%H}.log" TO_STANDARD_OUTPUT = true * FATAL: FILENAME = "log/fatal_%datetime{%Y%M%d%H}.log" TO_STANDARD_OUTPUT = true
配置项都非常的简单明了,GLOBAL是全局配置,然后下面是各级配置,各级日志配置项若为空,就选用的全局日志的配置项。要让自己的配置生效,需要在代码中新增一些逻辑:
#include "easylogging++.h" INITIALIZE_EASYLOGGINGPP void init() { el::Configurations conf("log.conf"); el::Loggers::reconfigureAllLoggers(conf); } int main() { init(); LOG(INFO) << "My first info log using default logger"; return 0; }
接着加上一个编译宏ELPP_NO_DEFAULT_LOG_FILE进行编译,否则无法生成自定义的日志文件:
$ g++ test.cpp -o main -std=c++11 -DELPP_NO_DEFAULT_LOG_FILE $ ./main $ ls easylogging++.h log log.conf logs main test.cpp $ ls log debug_2018060800.log error_2018060800.log fatal_2018060800.log info_2018060800.log warn_2018060800.log
可以看到,运行新的代码之后,目录下多了一个文件夹log,log文件下面就是我们自定义的日志文件了。这个效果是不是非常的棒棒呢?
另外easylogging++还支持线程安全,只需要编译的时候加上支持线程安全的编译宏——ELPP_THREAD_SAFE进行编译即可。其内部是通过mutex互斥锁的方式,实现的线程安全。这样在多线程环境下,也可以安全的使用easylogging++进行日志记录,确实非常的给力呢。