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++進行日志記錄,確實非常的給力呢。
