日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

日志库EasyLogging++学习系列(10)—— 日志文件滚动

發(fā)布時(shí)間:2025/3/12 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 日志库EasyLogging++学习系列(10)—— 日志文件滚动 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在很多應(yīng)用場(chǎng)合,我們是需要實(shí)現(xiàn)日志文件滾動(dòng)的,特別是在一些長(zhǎng)期運(yùn)行的服務(wù)器程序中,如果把所有的日志都記錄在一個(gè)文件之中,勢(shì)必會(huì)造成日志文件越來越大。當(dāng)日志內(nèi)容很多的時(shí)候,萬一哪天突然需要查詢某個(gè)日志信息就會(huì)顯得十分不便。所以,支持日志文件滾動(dòng)是很多日志庫都支持的功能,而文件滾動(dòng)又可以分為按大小滾動(dòng)和按時(shí)間滾動(dòng)。


按大小滾動(dòng)文件


在 Easylogging++ 中,已經(jīng)實(shí)現(xiàn)了按照日志文件大小來滾動(dòng)日志記錄。在前面《日志庫EasyLogging++學(xué)習(xí)系列(3)—— 配置功能》一文中介紹配置文件時(shí),有一個(gè)配置項(xiàng):MAX_LOG_FILE_SIZE,這個(gè)配置項(xiàng)的值(以字節(jié)為單位)表示的就是日志文件的最大大小。一旦日志文件的大小達(dá)到這個(gè)配置項(xiàng)設(shè)置的值,日志文件就會(huì)自動(dòng)清空文件中所有的日志記錄,并重新開始寫入。不過配置項(xiàng)?MAX_LOG_FILE_SIZE?在默認(rèn)情況下是不生效的,需要設(shè)置標(biāo)記:LoggingFlag::StrictLogFileSizeCheck 來激活。另外,如果我們想要保留之前的日志記錄,那么我們可以注冊(cè)一個(gè)回調(diào)函數(shù),這個(gè)回調(diào)函數(shù)將會(huì)允許我們?cè)谇蹇杖罩疚募皩?duì)日志文件進(jìn)行一次處理。下面的代碼演示了按大小滾動(dòng)日志文件,并通過回調(diào)函數(shù)保留了所有的日志記錄:

[cpp] view plaincopy print?
  • #include?"easylogging++.h"??
  • ??
  • INITIALIZE_EASYLOGGINGPP??
  • ??
  • static?unsigned?int?idx;??
  • ??
  • void?rolloutHandler(const?char*?filename,?std::size_t?size)???
  • {??
  • ????///?備份日志??
  • ????system("mkdir?bin");??
  • ????std::stringstream?ss;??
  • ????ss?<<?"move?"?<<?filename?<<?"?bin\\log_backup_"?<<?++idx;??
  • ????system(ss.str().c_str());??
  • }??
  • ??
  • int?main(int,?char**)??
  • {??
  • ????idx?=?0;??
  • ????el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck);??
  • ????el::Loggers::reconfigureAllLoggers(el::ConfigurationType::MaxLogFileSize,?"100");??
  • ??
  • ????///?注冊(cè)回調(diào)函數(shù)??
  • ????el::Helpers::installPreRollOutCallback(rolloutHandler);??
  • ??
  • ????for?(int?i?=?0;?i?<?100;?++i)??
  • ????{??
  • ????????LOG(INFO)?<<?"Test";??
  • ????}??
  • ??
  • ????///?注銷回調(diào)函數(shù)??
  • ????el::Helpers::uninstallPreRollOutCallback();??
  • ????return?0;??
  • }??
  • #include "easylogging++.h"INITIALIZE_EASYLOGGINGPPstatic unsigned int idx;void rolloutHandler(const char* filename, std::size_t size) {/// 備份日志system("mkdir bin");std::stringstream ss;ss << "move " << filename << " bin\\log_backup_" << ++idx;system(ss.str().c_str()); }int main(int, char**) {idx = 0;el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck);el::Loggers::reconfigureAllLoggers(el::ConfigurationType::MaxLogFileSize, "100");/// 注冊(cè)回調(diào)函數(shù)el::Helpers::installPreRollOutCallback(rolloutHandler);for (int i = 0; i < 100; ++i){LOG(INFO) << "Test";}/// 注銷回調(diào)函數(shù)el::Helpers::uninstallPreRollOutCallback();return 0; } 通過配置文件來設(shè)置 配置項(xiàng)? MAX_LOG_FILE_SIZE?的大小也可以實(shí)現(xiàn)上述演示代碼的效果,另外我們還可以設(shè)置不同級(jí)別的日志文件按照不同的文件大小來滾動(dòng)。如果不小心忘記了設(shè)置標(biāo)記:LoggingFlag::StrictLogFileSizeCheck ,我們還可以通過調(diào)用函數(shù)?el::Helpers::validateFileRolling(el::Logger*, const el::Level&) 以手動(dòng)的方式來檢查日志滾動(dòng),建議各位小伙伴可以自己嘗試一下。

    按時(shí)間滾動(dòng)文件


    在 Easylogging++ 中是沒有實(shí)現(xiàn)按時(shí)間滾動(dòng)日志文件的,不過既然是開源的日志庫,我們可以參考著按大小滾動(dòng)日志文件的實(shí)現(xiàn)方式,根據(jù)自己的需求去實(shí)現(xiàn)一個(gè)按時(shí)間滾動(dòng)日志文件的功能。下面簡(jiǎn)單地說明一下實(shí)現(xiàn)步驟:

    • 在按大小滾動(dòng)日志文件中有配置項(xiàng)?MAX_LOG_FILE_SIZE,所以我們也增加一個(gè)配置項(xiàng)?LOG_FILE_ROLLING_TIME ,新增配置項(xiàng)的值類型為 char* 型,其值只能是以下四個(gè):"MONTH" 、"DAY"、"HOUR"、"MINUTE",其中"MONTH"表示按月份滾動(dòng)日志文件,"DAY"表示按天數(shù)滾動(dòng)日志文件,"HOUR"表示按小時(shí)滾動(dòng)日志文件,"MINUTE"表示按分鐘滾動(dòng)日志文件。
    • 在按大小滾動(dòng)日志文件中有標(biāo)記?LoggingFlag::StrictLogFileSizeCheck 來激活滾動(dòng)功能,所以我們?cè)趯?shí)現(xiàn)按時(shí)間滾動(dòng)日志文件的功能中也增加一個(gè)標(biāo)記?LoggingFlag::StrictLogFileTimeCheck 來激活滾動(dòng)功能。
    • 在按大小滾動(dòng)日志文件中,允許我們?cè)谇蹇瘴募匦聦懭胫巴ㄟ^回調(diào)函數(shù)對(duì)日志文件進(jìn)行處理,所以我們?cè)?span style="font-family:'Microsoft YaHei'; font-size:14px; line-height:21.76px; background-color:rgb(248,248,248)">按時(shí)間滾動(dòng)日志文件的功能實(shí)現(xiàn)中,也同樣保留該回調(diào)函數(shù)的功能,但是在回調(diào)函數(shù)中增加了一個(gè)參數(shù),用來區(qū)分是按大小滾動(dòng)日志文件還是按時(shí)間滾動(dòng)日志文件。
    • 本文的最后提供了實(shí)現(xiàn)按時(shí)間滾動(dòng)日志文件功能的Easylogging++?源碼,實(shí)現(xiàn)的細(xì)節(jié)可在源碼中搜索“modify by Fish”來查看。 因本功能目前只限于本人在使用,如有錯(cuò)誤,歡迎指正。
    下面的代碼演示了如何使用新增的按時(shí)間滾動(dòng)日志文件的功能: [cpp] view plaincopy print?
  • #include?"easylogging++.h"??
  • ??
  • INITIALIZE_EASYLOGGINGPP??
  • ??
  • void?rolloutHandler(const?char*?filename,?std::size_t?size,?el::base::RollingLogFileBasis?rollingbasis)??
  • {??
  • ????switch?(rollingbasis)??
  • ????{??
  • ????case?el::base::RollingLogFileBasis::RollLog_FileSize:??
  • ????????///?按大小滾動(dòng)日志文件??
  • ????????break;??
  • ????case?el::base::RollingLogFileBasis::RollLog_DateTime:??
  • ????????///?按時(shí)間滾動(dòng)日志文件??
  • ????{??
  • ????????time_t?cuurenttime?=?time(NULL);??
  • ????????cuurenttime?-=?60;??
  • ??
  • ????????struct::tm?oneMinuteAgo;??
  • ????????localtime_s(&oneMinuteAgo,?&cuurenttime);??
  • ??
  • ????????std::string?filenameTemp?=?filename;??
  • ????????int?pos?=?filenameTemp.rfind('.');??
  • ????????filenameTemp?=?filenameTemp.substr(0,?pos);??
  • ????????char?backupFile[MAX_PATH]?=?{?0?};??
  • ????????sprintf_s(backupFile,?MAX_PATH,?"%s_%04d%02d%02d%02d%02d.log",?filenameTemp.c_str(),?oneMinuteAgo.tm_year?+?1900??
  • ????????????,?oneMinuteAgo.tm_mon?+?1,?oneMinuteAgo.tm_mday,?oneMinuteAgo.tm_hour,?oneMinuteAgo.tm_min);??
  • ??
  • ????????///?自定義日志備份??
  • ????????std::stringstream?ss;??
  • ????????ss?<<?"move?"?<<?filename?<<?"?"?<<?backupFile;??
  • ????????system(ss.str().c_str());??
  • ????}??
  • ????????break;??
  • ????default:??
  • ????????break;??
  • ????}??
  • }??
  • ??
  • int?main(int,?char**)??
  • {??
  • ????el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);??
  • ????el::Loggers::addFlag(el::LoggingFlag::StrictLogFileTimeCheck);??
  • ????el::Loggers::reconfigureAllLoggers(el::ConfigurationType::LogFileRollingTime,?"minute");????///?按分鐘滾動(dòng)日志文件??
  • ??
  • ????///?注冊(cè)回調(diào)函數(shù)??
  • ????el::Helpers::installPreRollOutCallback(rolloutHandler);??
  • ??
  • ????for?(int?i?=?0;?i?<?100000;?++i)??
  • ????{??
  • ????????LOG(DEBUG)?<<?"DEBUG";??
  • ????????LOG(INFO)?<<?"INFO";??
  • ????????DLOG(INFO)?<<?"DEBUG";??
  • ????????LOG(WARNING)?<<?"WARNING";??
  • ????????LOG(ERROR)?<<?"ERROR";??
  • ????????LOG(FATAL)?<<?"FATAL";??
  • ????????LOG(TRACE)?<<?"TRACE";??
  • ??
  • ????????VLOG(0)?<<?"VERBOSE";??
  • ????????Sleep(1000);??
  • ????}??
  • ??
  • ????///?注銷回調(diào)函數(shù)??
  • ????el::Helpers::uninstallPreRollOutCallback();??
  • ????return?0;??
  • }??
  • #include "easylogging++.h"INITIALIZE_EASYLOGGINGPPvoid rolloutHandler(const char* filename, std::size_t size, el::base::RollingLogFileBasis rollingbasis) {switch (rollingbasis){case el::base::RollingLogFileBasis::RollLog_FileSize:/// 按大小滾動(dòng)日志文件break;case el::base::RollingLogFileBasis::RollLog_DateTime:/// 按時(shí)間滾動(dòng)日志文件{time_t cuurenttime = time(NULL);cuurenttime -= 60;struct::tm oneMinuteAgo;localtime_s(&oneMinuteAgo, &cuurenttime);std::string filenameTemp = filename;int pos = filenameTemp.rfind('.');filenameTemp = filenameTemp.substr(0, pos);char backupFile[MAX_PATH] = { 0 };sprintf_s(backupFile, MAX_PATH, "%s_%04d%02d%02d%02d%02d.log", filenameTemp.c_str(), oneMinuteAgo.tm_year + 1900, oneMinuteAgo.tm_mon + 1, oneMinuteAgo.tm_mday, oneMinuteAgo.tm_hour, oneMinuteAgo.tm_min);/// 自定義日志備份std::stringstream ss;ss << "move " << filename << " " << backupFile;system(ss.str().c_str());}break;default:break;} }int main(int, char**) {el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);el::Loggers::addFlag(el::LoggingFlag::StrictLogFileTimeCheck);el::Loggers::reconfigureAllLoggers(el::ConfigurationType::LogFileRollingTime, "minute"); /// 按分鐘滾動(dòng)日志文件/// 注冊(cè)回調(diào)函數(shù)el::Helpers::installPreRollOutCallback(rolloutHandler);for (int i = 0; i < 100000; ++i){LOG(DEBUG) << "DEBUG";LOG(INFO) << "INFO";DLOG(INFO) << "DEBUG";LOG(WARNING) << "WARNING";LOG(ERROR) << "ERROR";LOG(FATAL) << "FATAL";LOG(TRACE) << "TRACE";VLOG(0) << "VERBOSE";Sleep(1000);}/// 注銷回調(diào)函數(shù)el::Helpers::uninstallPreRollOutCallback();return 0; }
    特別提醒:
    • 因?yàn)樵谛略霭磿r(shí)間滾動(dòng)日志文件的功能中修改了回調(diào)函數(shù),所以如果使用按大小滾動(dòng)日志文件功能,也需要使用修改后的回調(diào)函數(shù)。
    • 因?yàn)橹挥性谟腥罩緦懭氲臅r(shí)候才判斷是否需要更新文件,所以如果無日志記錄,日志文件是無法按時(shí)間滾動(dòng)的。

    在實(shí)際應(yīng)用中,如果日志按時(shí)間滾動(dòng),我們的日志文件基本上都會(huì)以時(shí)間來命名,所以為了更加方便地使用,我們可以在實(shí)現(xiàn)了按時(shí)間滾動(dòng)功能的代碼上再增加一個(gè)宏定義ELPP_NAME_LOG_FILE_AFTER_TIME。通過定義這個(gè)宏,我們實(shí)現(xiàn)了這樣一個(gè)功能:當(dāng)按時(shí)間滾動(dòng)日志時(shí),可以自動(dòng)地創(chuàng)建新的日志文件,并且會(huì)以滾動(dòng)時(shí)間命名新建文件。不過這個(gè)功能目前并不是很完善,使用起來有以下幾個(gè)限制條件:

    • 不同級(jí)別的日志必須保存在不同的日志文件中,否則無法實(shí)現(xiàn)日志滾動(dòng)。
    • 按月份滾動(dòng)的日志文件名中日期格式須配置:%datetime{%Y%M},如FILENAME = "log\\test_%datetime{%Y%M}.log"。
    • 按天數(shù)滾動(dòng)的日志文件名中日期格式須配置:%datetime{%Y%M%d},如FILENAME = "log\\test_%datetime{%Y%M%d}.log"。
    • 按小時(shí)滾動(dòng)的日志文件名中日期格式須配置:%datetime{%Y%M%d%H},如FILENAME = "log\\test_%datetime{%Y%M%d%H}.log"。
    • 按分鐘滾動(dòng)的日志文件名中日期格式須配置:%datetime{%Y%M%d%H%m},如FILENAM="log\\test_%datetime{%Y%M%d%H%m}.log"。
    雖然使用這個(gè)功能有些限制條件,但是這些條件基本符合我平時(shí)的使用習(xí)慣,因?yàn)椴煌?jí)別的日志在實(shí)際應(yīng)用中我肯定是會(huì)保存在不同的文件中,而且文件名中的日期格式也和滾動(dòng)的時(shí)間間隔一致,所以我也就沒有去完善這個(gè)功能。下面通過配置文件的方式演示了這個(gè)功能: [cpp] view plaincopy print?
  • #define?ELPP_NAME_LOG_FILE_AFTER_TIME??
  • #define?ELPP_NO_DEFAULT_LOG_FILE??
  • #include?"easylogging++.h"??
  • ??
  • INITIALIZE_EASYLOGGINGPP??
  • ??
  • int?main(int,?char**)??
  • {??
  • ????el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);??
  • ????el::Loggers::addFlag(el::LoggingFlag::StrictLogFileTimeCheck);??
  • ??
  • ????el::Configurations?conf("log.conf");??
  • ????el::Loggers::reconfigureAllLoggers(conf);??
  • ??
  • ????for?(int?i?=?0;?i?<?100000;?++i)??
  • ????{??
  • ????????LOG(DEBUG)?<<?"DEBUG";??
  • ????????LOG(INFO)?<<?"INFO";??
  • ????????LOG(WARNING)?<<?"WARNING";??
  • ????????LOG(ERROR)?<<?"ERROR";??
  • ????????LOG(FATAL)?<<?"FATAL";??
  • ????????LOG(TRACE)?<<?"TRACE";??
  • ??
  • ????????VLOG(0)?<<?"VERBOSE";??
  • ????????Sleep(1000);??
  • ????}??
  • ??
  • ????return?0;??
  • }??
  • #define ELPP_NAME_LOG_FILE_AFTER_TIME #define ELPP_NO_DEFAULT_LOG_FILE #include "easylogging++.h"INITIALIZE_EASYLOGGINGPPint main(int, char**) {el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);el::Loggers::addFlag(el::LoggingFlag::StrictLogFileTimeCheck);el::Configurations conf("log.conf");el::Loggers::reconfigureAllLoggers(conf);for (int i = 0; i < 100000; ++i){LOG(DEBUG) << "DEBUG";LOG(INFO) << "INFO";LOG(WARNING) << "WARNING";LOG(ERROR) << "ERROR";LOG(FATAL) << "FATAL";LOG(TRACE) << "TRACE";VLOG(0) << "VERBOSE";Sleep(1000);}return 0; }其中的配置文件 log.conf 內(nèi)容如下: [plain] view plaincopy print?
  • *?GLOBAL:??
  • ????FORMAT??????????????????=???"[%level?|?%datetime]?|?%msg"??
  • ????ENABLED?????????????????=???true??
  • ????TO_FILE?????????????????=???true??
  • ????TO_STANDARD_OUTPUT??????=???true??
  • ????LOG_FLUSH_THRESHOLD?????=???0??
  • ????MILLISECONDS_WIDTH??????=???3??
  • ????PERFORMANCE_TRACKING????=???false??
  • ????MAX_LOG_FILE_SIZE???????=???2097152?##?Throw?log?files?away?after?2097152?2MB?/?209715200?200MB?/?4398046511104?1GB??
  • ????LOG_FILE_ROLLING_TIME???=???minute??
  • *?INFO:??
  • ????FILENAME????????????????=???"log\\test_%datetime{%Y%M%d%H%m}_info.log"??
  • *?DEBUG:??
  • ????FILENAME????????????????=???"log\\test_%datetime{%Y%M%d%H%m}_debug.log"??
  • *?WARNING:??
  • ????FILENAME????????????????=???"log\\test_%datetime{%Y%M%d%H%m}_warning.log"??
  • *?TRACE:??
  • ????FILENAME????????????????=???"log\\test_%datetime{%Y%M%d%H%m}_trace.log"??
  • *?VERBOSE:??
  • ????FILENAME????????????????=???"log\\test_%datetime{%Y%M%d%H%m}_verbose.log"??
  • *?ERROR:??
  • ????FILENAME????????????????=???"log\\test_%datetime{%Y%M%d%H%m}_error.log"??
  • *?FATAL:??
  • ????FILENAME????????????????=???"log\\test_%datetime{%Y%M%d%H%m}_fatal.log"??
  • * GLOBAL:FORMAT = "[%level | %datetime] | %msg"ENABLED = trueTO_FILE = trueTO_STANDARD_OUTPUT = trueLOG_FLUSH_THRESHOLD = 0MILLISECONDS_WIDTH = 3PERFORMANCE_TRACKING = falseMAX_LOG_FILE_SIZE = 2097152 ## Throw log files away after 2097152 2MB / 209715200 200MB / 4398046511104 1GBLOG_FILE_ROLLING_TIME = minute * INFO:FILENAME = "log\\test_%datetime{%Y%M%d%H%m}_info.log" * DEBUG:FILENAME = "log\\test_%datetime{%Y%M%d%H%m}_debug.log" * WARNING:FILENAME = "log\\test_%datetime{%Y%M%d%H%m}_warning.log" * TRACE:FILENAME = "log\\test_%datetime{%Y%M%d%H%m}_trace.log" * VERBOSE:FILENAME = "log\\test_%datetime{%Y%M%d%H%m}_verbose.log" * ERROR:FILENAME = "log\\test_%datetime{%Y%M%d%H%m}_error.log" * FATAL:FILENAME = "log\\test_%datetime{%Y%M%d%H%m}_fatal.log"利用上述演示代碼,可以完全自動(dòng)地按照每分鐘的間隔創(chuàng)建如下格式的日志文件:

    按時(shí)間滾動(dòng)日志文件之所以寫了這么多,最主要的原因就是為了說明在開源的日志庫中,我們可以完全自主地按照自己的想法來實(shí)現(xiàn)一些符合自己需求的功能。比如上面介紹的宏定義ELPP_NAME_LOG_FILE_AFTER_TIME功能,雖然還不完善,但是只要嚴(yán)格按照限制條件來使用,完全可以達(dá)到我們想要的效果。對(duì)于開源代碼,能夠直接使用還并不是我們最終的目的,能夠在開源的基礎(chǔ)上加以修改完善并應(yīng)用于實(shí)際編程當(dāng)中才是我們學(xué)習(xí)開源代碼的初衷。
    猛戳這里,下載源碼!



    總結(jié)

    以上是生活随笔為你收集整理的日志库EasyLogging++学习系列(10)—— 日志文件滚动的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。