C++?Log4cpp跨平臺日志庫的使用小結
項目中,最重要的模塊之一就是日志了,今天這篇博客記錄項目中l(wèi)og4cpp的用法!
Log4cpp是c++類庫,用于靈活地記錄文件、syslog、IDSA和其他目的地。它是在Log4j Java庫之后建模的,盡可能地接近它們的API。
一、介紹
1. log4cpp的日志方式
log4cpp::FileAppender // 輸出到文件(常用)
log4cpp::RollingFileAppender // 輸出到回卷文件,即當文件到達某個大小后回卷(常用)
log4cpp::OstreamAppender // 輸出到一個ostream類(常用)
log4cpp::RemoteSyslogAppender // 輸出到遠程syslog服務器
log4cpp::StringQueueAppender // 內存隊列
log4cpp::SyslogAppender // 本地syslog
log4cpp::Win32DebugAppender // 發(fā)送到缺省系統(tǒng)調試器
log4cpp::NTEventLogAppender // 發(fā)送到win 事件日志
2.設置日志輸出的格式
log4cpp::FileAppender* appender = new log4cpp::FileAppender("appender", "text.log");
例如:
PatternLayout:自定義日志格式
log4cpp::PatternLayout *patternLayout = new log4cpp::PatternLayout(); patternLayout->setConversionPattern("%d [%p] - %m%n"); appender->setLayout(patternLayout);
PatternLayout支持以下一組格式字符:
- %% - 一個百分號;
- %c - the category;
- %d - date日期格式:日期格式字符后面可以跟著花括號括起來的日期格式說明符。例如,%d {% H: % M: % S、l %}或% d {% d % M H % Y %: % M: % S、l %}。如果沒有給出日期 格式說明符,則使用以下格式:"Wed Jan 02 02:03:55 1980"。日期格式說明符承認與 ANSI C函數strftime相同的語法,只是增加了1個。加號是以毫秒為單位的說明符%l,用 0填充為3位數字;
- %m - 你要輸出的日志信息;
- %n - 換行符;
- %p - 優(yōu)先級;
- %r - 該布局創(chuàng)建后的毫秒數;
- %R - 從1970年1月1日0時開始到目前為止的秒數;
- %u - 進程開始到目前為止的時鐘周期數;
- %x - the NDC;
- %t - 線程的名字;
- 默認情況下,PatternLayout的ConversionPattern設置為“%m%n”。
3. 設置日志的輸出優(yōu)先級
log4cpp::Category &root = log4cpp::Category::getRoot(); root.setPriority(log4cpp::Priority::NOTICE); root.addAppender(appender);
日志的級別總共有:
NOTSET < DEBUG < INFO < NOTICE < WARN < ERROR < CRIT < ALERT < FATAL = EMERG
日志級別的意思是低于該級別的日志不會被記錄。
二、Window
1. 下載log4cpp
log4cpp官網:
下載后解壓進入msvc10
因為官方提供的是vs2010編譯的項目,所以根據自己電腦裝的vs去打開即可,例如我這里使用vs2017去打開,打開后會提示升級,升級即可。
2. 編譯
3. 報錯解決1
不出意外的話,會報錯。
解決方法:①在log4cpp項目工程中找到NTEventLogCategories.mc文件,選擇該文件上然后右鍵選擇屬性,在彈出窗口中找到“配置屬性 - 自定義生成工具 - 常規(guī) - 命令行”中修改編譯命令,設置為如下命令:
if not exist $(OutDir) md $(OutDir) mc.exe -h $(OutDir) -r $(OutDir) $(ProjectDir)..\%(Filename).mc RC.exe -r -fo $(OutDir)%(Filename).res $(OutDir)%(Filename).rc link.exe /MACHINE:IX86 -dll -noentry -out:$(OutDir)NTEventLogAppender.dll $(OutDir)%(Filename).res
然后再次右鍵log4cpp,選擇重新編譯!
不出意外的話,再次報錯。
4. 報錯解決2
解決方法:由于log4cpp中對snprintf進行了重新實現(xiàn),visual studio的c庫對snprintf也有實現(xiàn),windows中在鏈接時會報snprintf函數沖突,所以需要設置log4cpp的預編譯項,選擇使用visual stuido中c庫的實現(xiàn),在log4cpp工程上點右鍵選屬性,在”配置屬性 - C/C++ - 預處理器 - 預處理器定義"中增加一條預處理定義 。
HAVE_SNPRINTF
再次編譯!
5. 編譯成功
不出意外的話,編譯通過!
進入路徑log4cpp-1.1.3\log4cpp\msvc10\log4cpp\Debug,編譯好的庫就在這里。
頭文件路徑:log4cpp-1.1.3\log4cpp
注意,這是編譯x86(Win32)的庫,如果需要編譯x64的庫,在項目中添加x64的庫后進行編譯即可;編譯好的庫路徑:log4cpp-1.1.3\log4cpp\msvc10\x64\Debug
Release庫編譯方式與上面方式一樣!
6. 測試
官方例子,稍作修改
新建項目,將上面編譯好的 log4cpp.dll 和 log4cpp.lib 和 /include 文件夾拷貝到項目路徑中去
#include "log4cpp/Category.hh" #include "log4cpp/Appender.hh" #include "log4cpp/FileAppender.hh" #include "log4cpp/OstreamAppender.hh" #include "log4cpp/Layout.hh" #include "log4cpp/BasicLayout.hh" #include "log4cpp/Priority.hh" #include "log4cpp/PatternLayout.hh" int main(void) { /* 1.日志輸出到控制臺 */ { log4cpp::Appender *appender1 = new log4cpp::OstreamAppender("console", &std::cout); appender1->setLayout(new log4cpp::BasicLayout()); // 默認配置 log4cpp::Category& root = log4cpp::Category::getRoot(); root.setPriority(log4cpp::Priority::WARN); root.addAppender(appender1); // 1.use of functions for logging messages root.debug("root debug"); root.warn("root warn"); root.error("root error"); root.info("root info"); // 2.printf-style for logging variables root.warn("%d + %d == %s ?", 1, 1, "two"); // 3.use of streams for logging messages root << log4cpp::Priority::ERROR << "Streamed root error"; root << log4cpp::Priority::INFO << "Streamed root info"; // 4.or this way: root.errorStream() << "Another streamed error"; root.debugStream() << "Another streamed debug"; } /* 2.日志輸出到控制臺和本地文件 */ { log4cpp::Appender *appender2 = new log4cpp::FileAppender("default", "program.log"); appender2->setLayout(new log4cpp::BasicLayout()); log4cpp::Category& sub1 = log4cpp::Category::getInstance(std::string("sub1")); sub1.addAppender(appender2); sub1.error("sub1 error"); sub1.warn("sub1 warn"); sub1 << log4cpp::Priority::ERROR << "Streamed sub1 error"; sub1 << log4cpp::Priority::WARN << "Streamed sub1 warn"; } /* 3.日志輸出到本地文件 */ { std::string logFileName = "test.log"; // 優(yōu)先級 log4cpp::Priority::PriorityLevel logPri = log4cpp::Priority::DEBUG; // 自定義布局 log4cpp::PatternLayout* logLayout = new log4cpp::PatternLayout(); logLayout->setConversionPattern("%d{%Y-%m-%d %H:%M:%S} [%p] : %m%n"); // 日志輸出到本地文件 log4cpp::FileAppender* logFile = new log4cpp::FileAppender("default", logFileName); logFile->setLayout(logLayout); // 設置自定義布局 // 輸出日志的操作類 log4cpp::Category& logCat = log4cpp::Category::getInstance("logCat"); logCat.addAppender(logFile); //設置優(yōu)先級 logCat.setPriority(logPri); logCat.error("測試 error"); logCat.debug("測試 debug"); logCat.warn("%d + %d == %s ?", 1, 1, "two"); logCat << log4cpp::Priority::ERROR << "Streamed root error"; logCat << log4cpp::Priority::INFO << "Streamed root info"; logCat.errorStream() << "Another streamed error"; logCat.debugStream() << "Another streamed debug"; } // 關閉日志 log4cpp::Category::shutdown(); return 0; }
三、Linux
1. 下載Log4cpp
可以通過上面的官網去下載,然后再拷入Linux系統(tǒng)中!
或者根據自己系統(tǒng)的特性,使用下面鏈接去下載,
https://nchc.dl.sourceforge.net/project/log4cpp/log4cpp-1.1.x%20%28new%29/log4cpp-1.1/log4cpp-1.1.3.tar.gz
例如Ubuntu:wget https://nchc.dl.sourceforge.net/project/log4cpp/log4cpp-1.1.x%20%28new%29/log4cpp-1.1/log4cpp-1.1.3.tar.gz
下載后,使用命令tar -zxvf log4cpp*.tar.gz 去解壓。
2. 編譯安裝
然后 cd log4cpp* 進入文件夾
然后執(zhí)行 ./configure
然后執(zhí)行 make
然后執(zhí)行 make install
即可安裝成功!
命令匯總:
wget https://nchc.dl.sourceforge.net/project/log4cpp/log4cpp-1.1.x%20%28new%29/log4cpp-1.1/log4cpp-1.1.3.tar.gz tar xzvf log4cpp-1.1.3.tar.gz cd log4cpp-1.1.3 ./configure make make install
安裝完畢后,log4cpp庫路徑在 /usr/local/lib
可以使用命令 mv -if /usr/local/lib/liblog4cpp.* 自己的項目路徑 拷貝到自己的項目路徑中去;例如,我會在項目路徑中創(chuàng)建一個lib文件夾,將剛剛安裝的log4cpp庫拷貝到此文件夾中
log4cpp頭文件路徑在 /usr/local/include/log4cpp
可以使用命令 mv -if /usr/local/include/log4cpp 自己的項目路徑 拷貝到自己的項目路徑中去;例如,我會在項目路徑中創(chuàng)建一個include文件夾,將剛剛安裝的log4cpp頭文件拷貝到此文件夾中
3. 測試
#include "log4cpp/Category.hh" #include "log4cpp/Appender.hh" #include "log4cpp/FileAppender.hh" #include "log4cpp/OstreamAppender.hh" #include "log4cpp/Layout.hh" #include "log4cpp/BasicLayout.hh" #include "log4cpp/Priority.hh" #include "log4cpp/PatternLayout.hh" int main(int argc, char **argv) { /* 1.日志輸出到控制臺 */ { log4cpp::Appender *appender1 = new log4cpp::OstreamAppender("console", &std::cout); appender1->setLayout(new log4cpp::BasicLayout()); // 默認配置 log4cpp::Category& root = log4cpp::Category::getRoot(); root.setPriority(log4cpp::Priority::WARN); root.addAppender(appender1); // 1.use of functions for logging messages root.debug("root debug"); root.warn("root warn"); root.error("root error"); root.info("root info"); // 2.printf-style for logging variables root.warn("%d + %d == %s ?", 1, 1, "two"); // 3.use of streams for logging messages root << log4cpp::Priority::ERROR << "Streamed root error"; root << log4cpp::Priority::INFO << "Streamed root info"; // 4.or this way: root.errorStream() << "Another streamed error"; root.debugStream() << "Another streamed debug"; } /* 2.日志輸出到控制臺和本地文件 */ { log4cpp::Appender *appender2 = new log4cpp::FileAppender("default", "program.log"); appender2->setLayout(new log4cpp::BasicLayout()); log4cpp::Category& sub1 = log4cpp::Category::getInstance(std::string("sub1")); sub1.addAppender(appender2); sub1.error("sub1 error"); sub1.warn("sub1 warn"); sub1 << log4cpp::Priority::ERROR << "Streamed sub1 error"; sub1 << log4cpp::Priority::WARN << "Streamed sub1 warn"; } /* 3.日志輸出到本地文件 */ { std::string logFileName = "test.log"; // 優(yōu)先級 log4cpp::Priority::PriorityLevel logPri = log4cpp::Priority::DEBUG; // 自定義布局 log4cpp::PatternLayout* logLayout = new log4cpp::PatternLayout(); logLayout->setConversionPattern("%d{%Y-%m-%d %H:%M:%S} [%p] : %m%n"); // 日志輸出到本地文件 log4cpp::FileAppender* logFile = new log4cpp::FileAppender("default", logFileName); logFile->setLayout(logLayout); // 設置自定義布局 // 輸出日志的操作類 log4cpp::Category& logCat = log4cpp::Category::getInstance("logCat"); logCat.addAppender(logFile); //設置優(yōu)先級 logCat.setPriority(logPri); logCat.error("測試 error"); logCat.debug("測試 debug"); logCat.warn("%d + %d == %s ?", 1, 1, "two"); logCat << log4cpp::Priority::ERROR << "Streamed root error"; logCat << log4cpp::Priority::INFO << "Streamed root info"; logCat.errorStream() << "Another streamed error"; logCat.debugStream() << "Another streamed debug"; } // 關閉日志 log4cpp::Category::shutdown(); return 0; }
編譯:
g++ test_log4cpp.cpp -I ./inlcude/ -L ./lib/ -llog4cpp1 -lpthread -o test_log4cpp
log4cpp1:是log4cpp.a靜態(tài)庫,我將名字改成這樣(在上圖中可以看到),才可以正常鏈接到靜態(tài)庫;不知道為什么,鏈接動態(tài)庫.so,編譯會報錯,所以只能鏈接靜態(tài)庫去完成編譯運行。
-I:指定頭文件路徑,可以使用相對路徑
-L:指定庫的路徑,可以使用相對路徑
四、log4cpp項目用法
以下介紹的項目用法,Linux和Window環(huán)境均可使用!
一般來說,日志都是由獨立的文件夾去保存的,下面為了方便就直接將日志保存在main函數同級目錄了。
1. 配置文件使用log4cpp
新建項目,在項目路徑下新建文件名為:log.conf
粘貼以下配置到log.conf文件中
#定義Root category的屬性 log4cpp.rootCategory=DEBUG, RootLog # 優(yōu)先級, 當前日志代表變量名 #定義RootLog屬性 #log4cpp.appender.RootLog = FileAppender # 輸出到文件 log4cpp.appender.RootLog = RollingFileAppender # 回卷 log4cpp.appender.RootLog.layout = PatternLayout # 自定義輸出日志格式 # 日志輸出格式 log4cpp.appender.RootLog.layout.ConversionPattern = %d{%Y-%m-%d %H:%M:%S.%l} [%t][%p] %m%n # 日志名 log4cpp.appender.RootLog.fileName = ./test.log # 單個日志文件大小 log4cpp.appender.RootLog.maxFileSize = 268435456 #256MB # 回卷日志個數名 log4cpp.appender.RootLog.fileNamePattern = test_%i.log # 日志個數 log4cpp.appender.RootLog.maxBackupIndex = 256 # append=true 信息追加到上面指定的日志文件中,false表示將信息覆蓋指定文件內容 log4cpp.appender.RootLog.append = true
在項目中新建文件MyLogger.h
#ifndef _MY_LOGGER_H_ #define _MY_LOGGER_H_ #include <string> #include <log4cpp/Category.hh> class MyLogger { public: bool init(const std::string &log_conf_file); // 指定加載log配置文件 static MyLogger *instance() { return &_instance; }; // 單例模式,返回自己 log4cpp::Category *GetHandle() { return _category; }; private: static MyLogger _instance; log4cpp::Category *_category; // 通過此對象可以實現(xiàn)日志寫入 }; /* 宏定義,方便調用 */ #define LOG_DEBUG MyLogger::instance()->GetHandle()->debug // 調試 #define LOG_INFO MyLogger::instance()->GetHandle()->info // 信息,消息 #define Log_NOTICE MyLogger::instance()->GetHandle()->notice // 通知 #define LOG_WARN MyLogger::instance()->GetHandle()->warn // 警告 #define LOG_ERROR MyLogger::instance()->GetHandle()->error // 錯誤 #define LOG_FATAL MyLogger::instance()->GetHandle()->fatal // 致命錯誤 /* * __LINE__ : 文件中的當前行號; * __FILE__ : 文件的完整路徑和文件名;如果用在包含文件中,則返回包含文件名; * __FUNCTION__ : 函數名字。 */ #define LOG(__level) log4cpp::Category::getRoot() << log4cpp::Priority::__level << "[" << __FUNCTION__ << "][" << __LINE__ << "]: " //#define LOG(__level) log4cpp::Category::getRoot() << log4cpp::Priority::__level << "[" << __FILE__ << "][" << __FUNCTION__ << "][" << __LINE__ << "]: " #endif
在項目中新建文件MyLogger.cpp
#include "MyLogger.h" #include <iostream> #include <log4cpp/FileAppender.hh> #include <log4cpp/PatternLayout.hh> #include <log4cpp/PropertyConfigurator.hh> // 靜態(tài)變量,需要在類外部初始化一下 MyLogger MyLogger::_instance; bool MyLogger::init(const std::string &log_conf_file) { try { log4cpp::PropertyConfigurator::configure(log_conf_file); // 初始化log配置文件 } catch (log4cpp::ConfigureFailure &f) { std::cerr << "load log config file " << log_conf_file.c_str() << " failed with result: " << f.what() << std::endl; return false; } // 初始化成功后,使用getRoot()獲取操作日志的對象 _category = &log4cpp::Category::getRoot(); return true; }
main函數測試
#include "MyLogger.h" int main(void) { if (!MyLogger::instance()->init("log.conf")) { fprintf(stderr, "init log module failed.\n"); return -1; } LOG_DEBUG("測試 debug."); LOG_INFO("測試 inof."); Log_NOTICE("測試 notice."); LOG_WARN("測試 warn."); LOG_ERROR("測試 error."); LOG_FATAL("測試 fatal."); LOG_DEBUG("%d + %c == %s", 1, 'a', "1a"); LOG(DEBUG) << "123"; LOG(ERROR) << "ERROR"; // 關閉日志 log4cpp::Category::shutdown(); return 0; }
運行結果:
在運行一次項目:
Linux編譯命令:(鏈接的是靜態(tài)庫)
g++ main.cpp MyLogger.h MyLogger.cpp -std=c++11 -I ./inlcude/ -L ./lib/ -llog4cpp1 -lpthread -o test_log4cpp
2. 純代碼使用log4cpp
網上找的代碼,感覺挺不錯的,拷貝過來做了修改,改成自己以后做項目可能會這樣使用!
MyLog.h
#ifndef _MY_LOG_H_ #define _MY_LOG_H_ #include <log4cpp/Category.hh> #include <log4cpp/FileAppender.hh> #include <log4cpp/PatternLayout.hh> #include <log4cpp/PropertyConfigurator.hh> #include <log4cpp/OstreamAppender.hh> #include <log4cpp/RollingFileAppender.hh> #include <string> // 優(yōu)先級 #define COUNT_PRITY log4cpp::Priority::INFO; // 控制臺 #define LOG_PRITY log4cpp::Priority::DEBUG; // 本地文件 /*采用單例模式設計,包含兩個category對象,一個負責輸出到屏幕的信息,一個負責記錄到日志的信息, 通過設置優(yōu)先級差別,可以實現(xiàn)所有信息都記錄在日志中,遇到error及以上的信息時打印到屏幕上*/ class MyLog { private: MyLog(bool b) { outToScreen = b; } ~MyLog() {} static MyLog * log; bool outToScreen;//是否輸出日志信息到屏幕 static std::string _screenInfo;//屏幕日志信息 static std::string _logName;//文件日志名稱 static log4cpp::Category& logCat; static log4cpp::Category& coutCat; static log4cpp::FileAppender* logFile;//文件日志輸入 static log4cpp::OstreamAppender* logScreen;//屏幕日志輸入 static log4cpp::RollingFileAppender *rollLogFile; /* 回卷用這個 */ static log4cpp::Priority::PriorityLevel logPri;//文件日志優(yōu)先級 static log4cpp::Priority::PriorityLevel coutPri;//屏幕日志優(yōu)先級 static log4cpp::PatternLayout* logLayout;//日志布局 static log4cpp::PatternLayout* screenLayout;//屏幕布局 static log4cpp::PatternLayout* logLayout2; /* 回卷用這個 */ private: // 返回當前年月日時分秒 static std::string getCurrentTime(std::string& year, std::string& month, std::string& day, std::string& hour, std::string& min, std::string& sec); public: // 初始化日志配置信息 static bool init(std::string logName = "time", bool toScreen = false); //獲取日志函數,默認參數選擇是否輸出到屏幕 static MyLog* getLog(bool toScreen = false); //銷毀日志對象 static void destoryLog(); //設置日志記錄優(yōu)先級 static void setPri(log4cpp::Priority::PriorityLevel coutLevel, log4cpp::Priority::PriorityLevel logLevel); //記錄日志,調用參數 __LINE__ ,__FUNCTION__ void warn(const char * msg, int line = __LINE__, const char *function = "warn"); void error(const char * msg, int line = __LINE__, const char *function = "error"); void debug(const char * msg, int line = __LINE__, const char *function = "debug"); void info(const char * msg, int line = __LINE__, const char *function = "info"); }; //為避免每次調用都要填寫參數__LINE__和__FUNCTION__,可以使用帶參數的宏定義 #define MyLogWARN(msg) MyLog::getLog()->warn(msg,__LINE__,__FUNCTION__); #define MyLogINFO(msg) MyLog::getLog()->info(msg,__LINE__,__FUNCTION__); #define MyLogERROR(msg) MyLog::getLog()->error(msg,__LINE__,__FUNCTION__); #define MyLogDEBUG(msg) MyLog::getLog()->debug(msg,__LINE__,__FUNCTION__); #endif
MyLog.cpp
#include "MyLog.h" #include <time.h> MyLog* MyLog::log = NULL; std::string MyLog::_screenInfo = "screenInfo"; std::string MyLog::_logName = "log"; log4cpp::Category& root = log4cpp::Category::getRoot(); log4cpp::Category& MyLog::logCat = root.getInstance(MyLog::_logName); log4cpp::Category& MyLog::coutCat = root.getInstance(MyLog::_screenInfo); // 優(yōu)先級 log4cpp::Priority::PriorityLevel MyLog::coutPri = COUNT_PRITY; // 控制臺 log4cpp::Priority::PriorityLevel MyLog::logPri = LOG_PRITY; // 本地文件 log4cpp::PatternLayout* MyLog::logLayout = NULL; log4cpp::PatternLayout* MyLog::screenLayout = NULL; log4cpp::PatternLayout* MyLog::logLayout2 = NULL; /* 回卷用這個 */ log4cpp::FileAppender* MyLog::logFile = NULL;//文件日志輸入 log4cpp::OstreamAppender* MyLog::logScreen = NULL;//屏幕日志輸入 log4cpp::RollingFileAppender *MyLog::rollLogFile; /* 回卷用這個 */ bool MyLog::init(std::string logName, bool toScreen) { // 判斷如果傳入文件名參數為空,或為默認參數,則使用當前年月日.log作為日志文件名 if (logName.empty() || logName == "time") { std::string year, month, day, hour, min, sec; getCurrentTime(year, month, day, hour, min, sec); logName = year + month + day + ".log"; } if (MyLog::log == NULL) { MyLog::log = new MyLog(toScreen); MyLog::_logName = logName; log4cpp::Category& logCat = root.getInstance(MyLog::_logName); log4cpp::Category& coutCat = root.getInstance(MyLog::_screenInfo); logScreen = new log4cpp::OstreamAppender("logScreen", &std::cout); logFile = new log4cpp::FileAppender("logFile", MyLog::_logName); /* 然后注釋這個 */ //rollLogFile = new log4cpp::RollingFileAppender("rollLogFile", MyLog::_logName, 1024*1024, 5); /* 回卷用這個 */ // 單個日志文件大小1M,5個回卷 //設置布局 MyLog::logLayout = new log4cpp::PatternLayout(); /* 然后注釋這個 */ MyLog::screenLayout = new log4cpp::PatternLayout(); MyLog::logLayout2 = new log4cpp::PatternLayout(); /* 回卷用這個 */ logLayout->setConversionPattern("%d{%Y-%m-%d %H:%M:%S} [%p] %m%n"); screenLayout->setConversionPattern("%d{%Y-%m-%d %H:%M:%S} [%p] %m%n"); logLayout2->setConversionPattern("%d{%Y-%m-%d %H:%M:%S} [%p] %m%n"); MyLog::logScreen->setLayout(screenLayout); MyLog::logFile->setLayout(logLayout); /* 然后注釋這個 */ //MyLog::rollLogFile->setLayout(logLayout2); /* 回卷用這個 */ //追加到目錄 MyLog::logCat.addAppender(MyLog::logFile); /* 然后注釋這個 */ //MyLog::logCat.addAppender(MyLog::rollLogFile); /* 回卷用這個 */ MyLog::coutCat.addAppender(MyLog::logScreen); //設置優(yōu)先級 MyLog::logCat.setPriority(MyLog::logPri); MyLog::coutCat.setPriority(MyLog::coutPri); } MyLog::log->outToScreen = toScreen; return true; } //獲取日志函數,默認參數選擇是否輸出到屏幕 MyLog* MyLog::getLog(bool toScreen) { MyLog::log->outToScreen = toScreen; if (NULL == MyLog::log) { printf("MyLog::log is NULL, please use MyLog::init!\n"); return NULL; } return MyLog::log; } //銷毀日志對象 void MyLog::destoryLog() { log4cpp::Category::shutdown(); delete MyLog::log; } //設置日志記錄優(yōu)先級 void MyLog::setPri(log4cpp::Priority::PriorityLevel coutLevel, log4cpp::Priority::PriorityLevel logLevel) { MyLog::logPri = logLevel; MyLog::coutPri = coutLevel; MyLog::logCat.setPriority(MyLog::logPri); MyLog::coutCat.setPriority(MyLog::coutPri); } //記錄日志,調用參數__FILE__, __LINE__ ,__FUNCTION__ void MyLog::warn(const char * msg, int line, const char *function) { char info[4096] = { 0 }; sprintf(info, "[%s][%d]: %s", function, line, msg); if (this->outToScreen) { logCat.warn(info); coutCat.warn(info); } else { logCat.warn(info); } } void MyLog::error(const char * msg, int line, const char *function) { char info[4096] = { 0 }; sprintf(info, "[%s][%d]: %s", function, line, msg); if (this->outToScreen) { logCat.error(info); coutCat.error(info); } else { logCat.error(info); } } void MyLog::debug(const char * msg, int line, const char *function) { char info[4096] = { 0 }; sprintf(info, "[%s][%d]: %s", function, line, msg); if (this->outToScreen) { logCat.debug(info); coutCat.debug(info); } else { logCat.debug(info); } } void MyLog::info(const char * msg, int line, const char *function) { char info[4096] = { 0 }; sprintf(info, "[%s][%d]: %s", function, line, msg); if (this->outToScreen) { logCat.info(info); coutCat.info(info); } else { logCat.info(info); } } std::string MyLog::getCurrentTime(std::string& year, std::string& month, std::string& day, std::string& hour, std::string& min, std::string& sec) { // 獲取系統(tǒng)時間 - 年月日時分秒 time_t _time; struct tm* target_time; time(&_time); target_time = localtime(&_time); year = std::to_string(target_time->tm_year + 1900); month = target_time->tm_mon + 1 > 9 ? std::to_string(target_time->tm_mon + 1) : "0" + std::to_string(target_time->tm_mon + 1); day = target_time->tm_mday > 9 ? std::to_string(target_time->tm_mday) : "0" + std::to_string(target_time->tm_mday); hour = target_time->tm_hour > 9 ? std::to_string(target_time->tm_hour) : "0" + std::to_string(target_time->tm_hour); min = target_time->tm_min > 9 ? std::to_string(target_time->tm_min) : "0" + std::to_string(target_time->tm_min); sec = target_time->tm_sec > 9 ? std::to_string(target_time->tm_sec) : "0" + std::to_string(target_time->tm_sec); return year + month + day + hour + min + sec; }
main函數測試
#include "MyLog.h" int main(void) { if (!MyLog::init("")) { fprintf(stderr, "init log module failed.\n"); return -1; } MyLogWARN("警告"); MyLogINFO("信息"); MyLogERROR("錯誤"); MyLogDEBUG("調試"); // 關閉日志 log4cpp::Category::shutdown(); return 0; }
運行結果:
Linux編譯命令:(鏈接的是靜態(tài)庫)
g++ main.cpp MyLog.h MyLog.cpp -std=c++11 -I ./inlcude/ -L ./lib/ -llog4cpp1 -lpthread -o test_log4cpp
五、總結
日志在項目中是必須使用的,如果看完此篇博客還是不太懂log4cpp日志如何使用,直接拷貝上面項目代碼去到自己的項目中就可以直接使用了!
到此這篇關于C++ Log4cpp跨平臺日志庫使用記錄(Window與Linux)的文章就介紹到這了,更多相關C++ Log4cpp內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Qt音視頻開發(fā)之音頻播放QAudioOutput的實現(xiàn)
這篇文章主要為大家詳細介紹了如何利用Qt實現(xiàn)音頻播放QAudioOutput功能,文中的示例代碼講解詳細,對我們學習Qt開發(fā)有一定的幫助,需要的可以參考一下2023-03-03C++?BoostAsyncSocket實現(xiàn)異步反彈通信的案例詳解
這篇文章主要為大家詳細介紹了C++?BoostAsyncSocket如何實現(xiàn)異步反彈通信,文中的示例代碼講解詳細,具有一定的學習價值,感興趣的可以了解一下2023-03-03