日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

日志库EasyLogging++学习系列(7)—— 记录方式详解

發布時間:2025/3/12 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 日志库EasyLogging++学习系列(7)—— 记录方式详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在前面所列文章的演示代碼中,其實已經展示了一部分記錄日志的方式。為了使用方便,在 Easylogging++ 中,通過使用宏的集合來完成日志記錄。


普通日志記錄


對于普通的日志記錄,我們可以選擇以下兩種比較常用的方式:

  • LOG(LEVEL)
  • CLOG(LEVEL, logger ID)
兩個宏定義的中 LEVEL 請參看《 日志庫EasyLogging++學習系列(2)—— 日志級別》,而宏CLOG(CUSTOM LOG)中的 logger ID 可以參看《 日志庫EasyLogging++學習系列(6)—— 日志記錄器》。下面的代碼簡單演示了如何使用這兩個宏:

[cpp] view plaincopy print?
  • #include?"easylogging++.h"??
  • ??
  • INITIALIZE_EASYLOGGINGPP??
  • ??
  • int?main(int?argc,?char**?argv)??
  • {??
  • ????///?可以直接使用,不記錄任何日志信息??
  • ????LOG(INFO);??
  • ????CLOG(INFO,?"default");??
  • ??
  • ????LOG(INFO)?<<?"Here?is?very?simple?example.";??
  • ????CLOG(INFO,?"default")?<<?"Here?is?very?simple?example.";??
  • ??????
  • ????system("pause");??
  • ????return?0;??
  • }??
  • #include "easylogging++.h"INITIALIZE_EASYLOGGINGPPint main(int argc, char** argv) {/// 可以直接使用,不記錄任何日志信息LOG(INFO);CLOG(INFO, "default");LOG(INFO) << "Here is very simple example.";CLOG(INFO, "default") << "Here is very simple example.";system("pause");return 0; }通過上面的演示代碼可以發現,其實 LOG(LEVEL) 就是 CLOG(LEVEL, "default") 的縮寫。不過,如果我們在包含頭文件? #include "easylogging++.h"?的代碼前面使用另外一個指定的 ID 來定義宏 ELPP_DEFAULT_LOGGER ,那么這個指定的 ID 就會自動地替換掉 "default" 。需要注意的是,這個指定 ID 所標識的日志記錄器必須保證使用前已經被注冊,否則,將無法正常使用宏 LOG(LEVEL) 來記錄日志信息。下面的代碼演示這個功能:

    [cpp] view plaincopy print?
  • #define?ELPP_DEFAULT_LOGGER?"testlog"??
  • #include?"easylogging++.h"??
  • ??
  • INITIALIZE_EASYLOGGINGPP??
  • ??
  • int?main(int?argc,?char**?argv)??
  • {??
  • ????///?使用前,注冊ID為testlog的日志記錄器??
  • ????el::Logger*?newLogger?=?el::Loggers::getLogger("testlog");??
  • ????LOG(INFO)?<<?"Here?is?very?simple?example.";??
  • ??
  • ????system("pause");??
  • ????return?0;??
  • }??
  • #define ELPP_DEFAULT_LOGGER "testlog" #include "easylogging++.h"INITIALIZE_EASYLOGGINGPPint main(int argc, char** argv) {/// 使用前,注冊ID為testlog的日志記錄器el::Logger* newLogger = el::Loggers::getLogger("testlog");LOG(INFO) << "Here is very simple example.";system("pause");return 0; }
    條件日志記錄


    條件日志就是只有當滿足某一個條件的時候才進行日志記錄,否則將忽略記錄。下面是記錄條件日志的兩個宏定義:

    • LOG_IF(condition, LEVEL)
    • CLOG_IF(condition, LEVEL, logger ID)

    上面兩個宏定義中 condition 條件為真時,日志信息才被記錄,在某些應用場景下這會顯得十分便利,下面的代碼演示了條件日志宏定義的用法:

    [cpp] view plaincopy print?
  • #include?"easylogging++.h"??
  • ??
  • INITIALIZE_EASYLOGGINGPP??
  • ??
  • int?main(int?argc,?char**?argv)??
  • {??
  • ????///?下面這三個日志,只有第一個會輸出??
  • ????LOG_IF(1?==?1,?INFO)?<<?"1?is?equal?to?1";??
  • ??
  • ????LOG_IF(1?>?2,?INFO)?<<?"1?is?greater?than?2";??
  • ??
  • ????LOG_IF(1?==?2,?DEBUG)?<<?"1?is?equal?to?2";??
  • ??
  • ????system("pause");??
  • ????return?0;??
  • }??
  • #include "easylogging++.h"INITIALIZE_EASYLOGGINGPPint main(int argc, char** argv) {/// 下面這三個日志,只有第一個會輸出LOG_IF(1 == 1, INFO) << "1 is equal to 1";LOG_IF(1 > 2, INFO) << "1 is greater than 2";LOG_IF(1 == 2, DEBUG) << "1 is equal to 2";system("pause");return 0; }
    偶然日志記錄


    偶然日志可以分為以下三種常見的情況,具體使用方法請參考示例代碼:

    • 每 N 次記錄一次日志,對應的宏定義是:LOG_EVERY_N(n, LEVEL) 或者?CLOG_EVERY_N(n, LEVEL, logger ID)

    • 當計數達到 N 次之后,才開始記錄日志,對應的宏定義是:LOG_AFTER_N(n, LEVEL)

    • 當記錄次數達到 N 次之后,就不再記錄日志信息,對應的宏定義是:LOG_N_TIMES(n, LEVEL)

    [cpp] view plaincopy print?
  • #include?"easylogging++.h"??
  • ??
  • INITIALIZE_EASYLOGGINGPP??
  • ??
  • int?main(int?argc,?char**?argv)??
  • {??
  • ????///?每?N?次記錄一次日志??
  • ????for?(int?i?=?1;?i?<=?200;?++i)??
  • ????{??
  • ????????LOG_EVERY_N(20,?INFO)?<<?"LOG_EVERY_N?i?=?"?<<?i;??
  • ????????LOG_EVERY_N(100,?INFO)?<<?"LOG_EVERY_N?Current?position?is?"?<<?ELPP_COUNTER_POS;??
  • ????}??
  • ??
  • ????///?當計數達到?N?次之后,才開始記錄日志??
  • ????for?(int?i?=?1;?i?<=?10;?++i)???
  • ????{??
  • ????????LOG_AFTER_N(6,?INFO)?<<?"LOG_AFTER_N?i?=?"?<<?i;??
  • ????}??
  • ??
  • ????///?當記錄次數達到?N?次之后,就不再記錄??
  • ????for?(int?i?=?1;?i?<?10;?++i)???
  • ????{??
  • ????????LOG_N_TIMES(6,?INFO)?<<?"LOG_N_TIMES?i?=?"?<<?i;??
  • ????}??
  • ??
  • ????system("pause");??
  • ????return?0;??
  • }??
  • #include "easylogging++.h"INITIALIZE_EASYLOGGINGPPint main(int argc, char** argv) {/// 每 N 次記錄一次日志for (int i = 1; i <= 200; ++i){LOG_EVERY_N(20, INFO) << "LOG_EVERY_N i = " << i;LOG_EVERY_N(100, INFO) << "LOG_EVERY_N Current position is " << ELPP_COUNTER_POS;}/// 當計數達到 N 次之后,才開始記錄日志for (int i = 1; i <= 10; ++i) {LOG_AFTER_N(6, INFO) << "LOG_AFTER_N i = " << i;}/// 當記錄次數達到 N 次之后,就不再記錄for (int i = 1; i < 10; ++i) {LOG_N_TIMES(6, INFO) << "LOG_N_TIMES i = " << i;}system("pause");return 0; }
    STL容器日志記錄


    在前面的文章《日志庫EasyLogging++學習系列(5)—— 輔助配置功能》中,已經給過示例演示了如何記錄 STL 容器日志的方式。再次提示,使用 STL容器日志記錄需要定義宏?ELPP_STL_LOGGING,每個容器默認最大容量是 100。下面是 Easylogging++ 支持的 STL 容器類型:


    ****
    std::vectorstd::liststd::dequestd::queue
    std::stackstd::priority_queuestd::setstd::multiset
    std::pairstd::bitsetstd::mapstd::multimap
    下面的是 C++11 標準才支持的 STL 容器,在? Easylogging++ V9.80版本中定義相應的宏就可以使用,別忘記同樣還需要定義宏?ELPP_STL_LOGGING


    TemplateMacro Needed
    std::arrayELPP_LOG_STD_ARRAY
    std::unordered_mapELPP_LOG_UNORDERED_MAP
    std::unordered_multimapELPP_LOG_UNORDERED_MAP
    std::unordered_setELPP_LOG_UNORDERED_SET
    std::unordered_multisetELPP_LOG_UNORDERED_SET

    系統日志記錄


    系統日志需要系統具有頭文件 syslog.h 的支持,這個頭文件在 Linux 系統下才有,也就是說Windows 系統是不支持 Easylogging++ 的系統日志功能的。因為我并沒有在 linux下用過 Easylogging++,在這里只簡單介紹一下。如果想要使用系統日志功能,必須先定義宏ELPP_SYSLOG?的,系統日志默認使用 ID 為 “syslog” 的日志記錄器,可以用以下的宏記錄日志:

    • SYSLOG(LEVEL)
    • SYSLOG_IF(Condition, LEVEL)
    • SYSLOG_EVERY_N(n, LEVEL)
    • CSYSLOG(LEVEL, loggerId)
    • CSYSLOG_IF(Condition, LEVEL, loggerId)
    • CSYSLOG_EVERY_N(n, LEVEL, loggerId)
    系統日志只支持以下幾個級別的日志,分別對應系統的優先級:
    • INFO (LOG_INFO)
    • DEBUG (LOG_DEBUG)
    • WARNING (LOG_WARNING)
    • ERROR (LOG_ERR)
    • FATAL (LOG_EMERG)


    CHECK宏日志記錄
    利用CHECK宏日志可以快速地判斷某個條件是否滿足,當滿足條件時不作記錄;而不滿足條件時就會記錄 FATAL 級別的日志,并且會中斷程序,除非你添加了標記 DisableApplicationAbortOnFatalLog?,下面是 Easylogging++ 支持的 CHECK 宏:
    CHECK NameNotes + Example
    CHECK(condition)Checks for condition e.g,?CHECK(isLoggedIn()) << "Not logged in";
    CHECK_EQ(a, b)Equality check e.g,?CHECK_EQ(getId(), getLoggedOnId()) << "Invalid user logged in";
    CHECK_NE(a, b)Inequality check e.g,?CHECK_NE(isUserBlocked(userId), false) << "User is blocked";
    CHECK_LT(a, b)Less than e.g,?CHECK_LT(1, 2) << "How 1 is not less than 2";
    CHECK_GT(a, b)Greater than e.g,?CHECK_GT(2, 1) << "How 2 is not greater than 1?";
    CHECK_LE(a, b)Less than or equal e.g,?CHECK_LE(1, 1) << "1 is not equal or less than 1";
    CHECK_GE(a, b)Greater than or equal e.g,?CHECK_GE(1, 1) << "1 is not equal or greater than 1";
    CHECK_NOTNULL(pointer)Ensures pointer is not null - if OK returns pointer e.g,?explicit MyClass(Obj* obj) : m_obj(CHECK_NOT_NULL(obj)) {}
    CHECK_STREQ(str1, str2)C-string equality (case-sensitive) e.g,?CHECK_STREQ(argv[1], "0") << "First arg cannot be 0";
    CHECK_STRNE(str1, str2)C-string inequality (case-sensitive) e.g,?CHECK_STRNE(username1, username2) << "Usernames cannot be same";
    CHECK_STRCASEEQ(str1, str2)C-string inequality (case-insensitive) e.g,?CHECK_CASESTREQ(argv[1], "Z") << "First arg cannot be 'z' or 'Z'";
    CHECK_STRCASENE(str1, str2)C-string inequality (case-insensitive) e.g,CHECK_STRCASENE(username1, username2) << "Same username not allowed";
    CHECK_BOUNDS(val, min, max)Checks that?val?falls under the?min?and?max?range e.g,CHECK_BOUNDS(i, 0, list.size() - 1) << "Index out of bounds";
    詳細的用法請看演示代碼,需要特別注意的是宏 CHECK_NOTNULL(pointer)?的用法: [cpp] view plaincopy print?
  • #include?"easylogging++.h"??
  • ??
  • INITIALIZE_EASYLOGGINGPP??
  • ??
  • int?main(void)???
  • {??
  • ????el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);??
  • ??
  • ????///?CHECK(condition)??
  • ????CHECK(1?<?2)?<<?"CHECK(condition)?example?1";??????//?condition為真時不記錄??
  • ????CHECK(1?>?2)?<<?"CHECK(condition)?example?2";??????//?condition為假時才記錄??
  • ??
  • ????///?CHECK_EQ(a,?b)??
  • ????CHECK_EQ(1,?1)?<<?"CHECK_EQ(a,?b)?example?1";?????//?滿足a?=?b時不記錄??
  • ????CHECK_EQ(1,?0)?<<?"CHECK_EQ(a,?b)?example?3";?????//?不滿足a?=?b時記錄??
  • ??
  • ????///?CHECK_NE(a,?b)???
  • ????CHECK_NE(1,?2)?<<?"CHECK_NE(a,?b)?example?1";?????//?滿足a?!=?b?時不記錄??
  • ????CHECK_NE(1,?1)?<<?"CHECK_NE(a,?b)?example?2";?????//?不滿足a?!=?b?時記錄??
  • ??
  • ????///?CHECK_LT(a,?b)???
  • ????CHECK_LT(1,?2)?<<?"CHECK_LT(a,?b)?example?1";?????//?滿足a?<?b時不記錄??
  • ????CHECK_LT(1,?1)?<<?"CHECK_LT(a,?b)?example?2";?????//?不滿足a?<?b時記錄??
  • ??
  • ????///?CHECK_GT(a,?b)???
  • ????CHECK_GT(2,?1)?<<?"CHECK_GT(a,?b)?example?1";?????//?滿足a?>?b時不記錄??
  • ????CHECK_GT(1,?1)?<<?"CHECK_GT(a,?b)?example?2";?????//?不滿足a?>?b時記錄??
  • ??
  • ????///?CHECK_LE(a,?b)???
  • ????CHECK_LE(1,?1)?<<?"CHECK_LE(a,?b)?example?1";?????//?滿足a?<=?b時不記錄??
  • ????CHECK_LE(1,?0)?<<?"CHECK_LE(a,?b)?example?2";?????//?不滿足a?<=?b時記錄??
  • ??
  • ????///?CHECK_GE(a,?b)???
  • ????CHECK_GE(1,?1)?<<?"CHECK_GE(a,?b)?example?1";?????//?滿足a?>=?b時不記錄??
  • ????CHECK_GE(1,?2)?<<?"CHECK_GE(a,?b)?example?2";?????//?不滿足a?>=?b時記錄??
  • ??
  • ????///?CHECK_STREQ(str1,?str2)?C風格字符串區分大小寫??
  • ????CHECK_STREQ("abc",?"abc")?<<?"CHECK_STREQ(str1,?str2)?example?1";?//?滿足str1?=?str2時不記錄??
  • ????CHECK_STREQ("abc",?"ABC")?<<?"CHECK_STREQ(str1,?str2)?example?2";?//?不滿足str1?=?str2時記錄??
  • ??
  • ????///?CHECK_STRNE(str1,?str2)?C風格字符串區分大小寫??
  • ????CHECK_STRNE("abc",?"ABC")?<<?"CHECK_STRNE(str1,?str2)?example?1";???//?滿足str1?!=?str2時不記錄??
  • ????CHECK_STRNE("abc",?"abc")?<<?"CHECK_STRNE(str1,?str2)?example?2";???//?不滿足str1?!=?str2時記錄??
  • ??
  • ????///?CHECK_STRCASEEQ(str1,?str2)?C風格字符串不區分大小寫??
  • ????CHECK_STRCASEEQ("abc",?"ABC")?<<?"CHECK_STRCASEEQ(str1,?str2)?example?1";?//?滿足str1?=?str2時不記錄??
  • ????CHECK_STRCASEEQ("abc",?"abd")?<<?"CHECK_STRCASEEQ(str1,?str2)?example?2";?//?不滿足str1?=?str2時記錄??
  • ??
  • ????///?CHECK_STRCASENE(str1,?str2)?C風格字符串不區分大小寫??
  • ????CHECK_STRCASENE("abc",?"abd")?<<?"CHECK_STRCASENE(str1,?str2)?example?1";?//?滿足str1?!=?str2時不記錄??
  • ????CHECK_STRCASENE("abc",?"ABC")?<<?"CHECK_STRCASENE(str1,?str2)?example?2";?//?不滿足str1?!=?str2時記錄??
  • ??
  • ????///?CHECK_NOTNULL(pointer)?判斷指針pointer是否為空,不為空時返回pointer??
  • ????int*?f?=?nullptr;??
  • ????if?(CHECK_NOTNULL(f))??
  • ????{??
  • ????}??
  • ??
  • ????f?=?new?int;??
  • ????if?(CHECK_NOTNULL(f))??
  • ????{??
  • ????}??
  • ????delete?f;??
  • ????f?=?nullptr;??
  • ??
  • ????int?min?=?2;??
  • ????int?max?=?5;??
  • ????CHECK_BOUNDS(1,?min,?max)?<<?"CHECK_BOUNDS(val,?min,?max)?example?1";??
  • ????CHECK_BOUNDS(2,?min,?max)?<<?"CHECK_BOUNDS(val,?min,?max)?example?2";??
  • ????CHECK_BOUNDS(3,?min,?max)?<<?"CHECK_BOUNDS(val,?min,?max)?example?3";??
  • ????CHECK_BOUNDS(4,?min,?max)?<<?"CHECK_BOUNDS(val,?min,?max)?example?4";??
  • ????CHECK_BOUNDS(5,?min,?max)?<<?"CHECK_BOUNDS(val,?min,?max)?example?5";??
  • ????CHECK_BOUNDS(6,?min,?max)?<<?"CHECK_BOUNDS(val,?min,?max)?example?6";??
  • ??
  • ????system("pause");??
  • ????return?0;??
  • }??
  • #include "easylogging++.h"INITIALIZE_EASYLOGGINGPPint main(void) {el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);/// CHECK(condition)CHECK(1 < 2) << "CHECK(condition) example 1"; // condition為真時不記錄CHECK(1 > 2) << "CHECK(condition) example 2"; // condition為假時才記錄/// CHECK_EQ(a, b)CHECK_EQ(1, 1) << "CHECK_EQ(a, b) example 1"; // 滿足a = b時不記錄CHECK_EQ(1, 0) << "CHECK_EQ(a, b) example 3"; // 不滿足a = b時記錄/// CHECK_NE(a, b) CHECK_NE(1, 2) << "CHECK_NE(a, b) example 1"; // 滿足a != b 時不記錄CHECK_NE(1, 1) << "CHECK_NE(a, b) example 2"; // 不滿足a != b 時記錄/// CHECK_LT(a, b) CHECK_LT(1, 2) << "CHECK_LT(a, b) example 1"; // 滿足a < b時不記錄CHECK_LT(1, 1) << "CHECK_LT(a, b) example 2"; // 不滿足a < b時記錄/// CHECK_GT(a, b) CHECK_GT(2, 1) << "CHECK_GT(a, b) example 1"; // 滿足a > b時不記錄CHECK_GT(1, 1) << "CHECK_GT(a, b) example 2"; // 不滿足a > b時記錄/// CHECK_LE(a, b) CHECK_LE(1, 1) << "CHECK_LE(a, b) example 1"; // 滿足a <= b時不記錄CHECK_LE(1, 0) << "CHECK_LE(a, b) example 2"; // 不滿足a <= b時記錄/// CHECK_GE(a, b) CHECK_GE(1, 1) << "CHECK_GE(a, b) example 1"; // 滿足a >= b時不記錄CHECK_GE(1, 2) << "CHECK_GE(a, b) example 2"; // 不滿足a >= b時記錄/// CHECK_STREQ(str1, str2) C風格字符串區分大小寫CHECK_STREQ("abc", "abc") << "CHECK_STREQ(str1, str2) example 1"; // 滿足str1 = str2時不記錄CHECK_STREQ("abc", "ABC") << "CHECK_STREQ(str1, str2) example 2"; // 不滿足str1 = str2時記錄/// CHECK_STRNE(str1, str2) C風格字符串區分大小寫CHECK_STRNE("abc", "ABC") << "CHECK_STRNE(str1, str2) example 1"; // 滿足str1 != str2時不記錄CHECK_STRNE("abc", "abc") << "CHECK_STRNE(str1, str2) example 2"; // 不滿足str1 != str2時記錄/// CHECK_STRCASEEQ(str1, str2) C風格字符串不區分大小寫CHECK_STRCASEEQ("abc", "ABC") << "CHECK_STRCASEEQ(str1, str2) example 1"; // 滿足str1 = str2時不記錄CHECK_STRCASEEQ("abc", "abd") << "CHECK_STRCASEEQ(str1, str2) example 2"; // 不滿足str1 = str2時記錄/// CHECK_STRCASENE(str1, str2) C風格字符串不區分大小寫CHECK_STRCASENE("abc", "abd") << "CHECK_STRCASENE(str1, str2) example 1"; // 滿足str1 != str2時不記錄CHECK_STRCASENE("abc", "ABC") << "CHECK_STRCASENE(str1, str2) example 2"; // 不滿足str1 != str2時記錄/// CHECK_NOTNULL(pointer) 判斷指針pointer是否為空,不為空時返回pointerint* f = nullptr;if (CHECK_NOTNULL(f)){}f = new int;if (CHECK_NOTNULL(f)){}delete f;f = nullptr;int min = 2;int max = 5;CHECK_BOUNDS(1, min, max) << "CHECK_BOUNDS(val, min, max) example 1";CHECK_BOUNDS(2, min, max) << "CHECK_BOUNDS(val, min, max) example 2";CHECK_BOUNDS(3, min, max) << "CHECK_BOUNDS(val, min, max) example 3";CHECK_BOUNDS(4, min, max) << "CHECK_BOUNDS(val, min, max) example 4";CHECK_BOUNDS(5, min, max) << "CHECK_BOUNDS(val, min, max) example 5";CHECK_BOUNDS(6, min, max) << "CHECK_BOUNDS(val, min, max) example 6";system("pause");return 0; }
    printf風格日志記錄
    如果編譯器支持 C++11 標準的可變參數模板,那么我們可以像 printf 函數一樣來記錄日志,唯一和 printf 函數不一樣的是,我們只需用 %v 來帶代替所有的參數即可,而不需要根據變量類型來指定格式。如果想要輸出 %v ,只需加上轉義字符 %%v 即可。請看下面 el::Logger 類的成員函數:
    • info(const char*, const T&, const Args&...)
    • warn(const char*, const T&, const Args&...)
    • error(const char*, const T&, const Args&...)
    • debug(const char*, const T&, const Args&...)
    • fatal(const char*, const T&, const Args&...)
    • trace(const char*, const T&, const Args&...)
    • verbose(int vlevel, const char*, const T&, const Args&...)
    下面的代碼演示了printf風格日志記錄的使用方法: [cpp] view plaincopy print?
  • #define??ELPP_STL_LOGGING??
  • #include?"easylogging++.h"??
  • ??
  • INITIALIZE_EASYLOGGINGPP??
  • ??
  • int?main(int?argc,?char**?argv)???
  • {??
  • ????el::Logger*?defaultLogger?=?el::Loggers::getLogger("default");??
  • ??
  • ????std::vector<int>?i;??
  • ????i.push_back(1);??
  • ????i.push_back(2);??
  • ??
  • ????///?記錄STL容器數據??
  • ????defaultLogger->warn("My?first?ultimate?log?message?%v?%v?%v",?123,?222,?i);??
  • ??
  • ????//?利用轉義字符輸出?%?和?%v??
  • ????defaultLogger->info("My?first?ultimate?log?message?%%?%%v?%v?%v",?123,?222);???
  • ??
  • ????system("pause");??
  • ????return?0;??
  • }??
  • #define ELPP_STL_LOGGING #include "easylogging++.h"INITIALIZE_EASYLOGGINGPPint main(int argc, char** argv) {el::Logger* defaultLogger = el::Loggers::getLogger("default");std::vector<int> i;i.push_back(1);i.push_back(2);/// 記錄STL容器數據defaultLogger->warn("My first ultimate log message %v %v %v", 123, 222, i);// 利用轉義字符輸出 % 和 %vdefaultLogger->info("My first ultimate log message %% %%v %v %v", 123, 222); system("pause");return 0; }


    perror風格日志記錄

    在C語言庫函數中有個errno變量,每個errno值對應著以字符串表示的錯誤類型。當你調用某些庫函數出錯時,被調用的函數會重新設置了errno的值,而 perror() 函數就是用于將你輸入的一些信息和現在的errno所對應的錯誤一起輸出。在 Easylogging++ 中,也支持在作用上類似 perror() 函數的宏定義:

    • PLOG(LEVEL)
    • PLOG_IF(Condition,?LEVEL)
    • PCHECK()
    • CPLOG(LEVEL, LoggerId)
    • CPLOG_IF(Condition, LEVEL, LoggerId)

    下面的代碼演示了 perror 風格日志記錄的使用方式:

    [cpp] view plaincopy print?
  • #include?"easylogging++.h"??
  • ??
  • INITIALIZE_EASYLOGGINGPP??
  • ??
  • int?main(void)???
  • {??
  • ????el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);??
  • ??
  • ????///?讀取一個不存在的文件,改變errno變量的值??
  • ????std::fstream?f("a?file?that?does?not?exist",?std::ifstream::in);??
  • ??
  • ????///?PLOG(LEVEL)??
  • ????PLOG(INFO)?<<?"A?message?with?plog";??
  • ??
  • ????///?PLOG_IF(Condition,?LEVEL),?條件為真時才記錄??
  • ????PLOG_IF(true,?INFO)?<<?"A?message?with?plog?1";??
  • ????PLOG_IF(false,?INFO)?<<?"A?message?with?plog?2";??
  • ??
  • ????///?PCHECK()??滿足條件不記錄,不滿足才記錄??
  • ????PCHECK(true)?<<?"check?message?with?plog?1";??
  • ????PCHECK(false)?<<?"check?message?with?plog?2";??
  • ??
  • ????system("pause");??
  • ????return?0;??
  • }??
  • #include "easylogging++.h"INITIALIZE_EASYLOGGINGPPint main(void) {el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);/// 讀取一個不存在的文件,改變errno變量的值std::fstream f("a file that does not exist", std::ifstream::in);/// PLOG(LEVEL)PLOG(INFO) << "A message with plog";/// PLOG_IF(Condition, LEVEL), 條件為真時才記錄PLOG_IF(true, INFO) << "A message with plog 1";PLOG_IF(false, INFO) << "A message with plog 2";/// PCHECK() 滿足條件不記錄,不滿足才記錄PCHECK(true) << "check message with plog 1";PCHECK(false) << "check message with plog 2";system("pause");return 0; }
    DEBUG模式日志記錄


    在前面的文章《日志庫EasyLogging++學習系列(2)—— 日志級別》中,簡單地提到了DEBUG模式的日志記錄。所謂的DEBUG模式,就是只在Debug版本的程序中才有意義,而在Release版本的程序中則沒有意義。在本文以上內容所提到的全部的日志記錄方式中,只要是以宏定義形式記錄日志信息的,基本上都會有一個DEBUG模式對應的宏定義。在 Easylogging++ 中,所有用于DEBUG模式的宏定義都是以大寫字母 D 開頭的,由于DEBUG模式宏定義的使用方式和常規的宏定義使用方式都是一樣的,這里不再贅述,建議有興趣了解更多關于DEBUG模式日志詳細信息的小伙伴可以親自動手試一試。

    總結

    以上是生活随笔為你收集整理的日志库EasyLogging++学习系列(7)—— 记录方式详解的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。