C++?Log4cpp跨平臺日志庫的使用小結(jié)
項目中,最重要的模塊之一就是日志了,今天這篇博客記錄項目中l(wèi)og4cpp的用法!
Log4cpp是c++類庫,用于靈活地記錄文件、syslog、IDSA和其他目的地。它是在Log4j Java庫之后建模的,盡可能地接近它們的API。
一、介紹
1. log4cpp的日志方式
log4cpp::FileAppender // 輸出到文件(常用)
log4cpp::RollingFileAppender // 輸出到回卷文件,即當文件到達某個大小后回卷(常用)
log4cpp::OstreamAppender // 輸出到一個ostream類(常用)
log4cpp::RemoteSyslogAppender // 輸出到遠程syslog服務(wù)器
log4cpp::StringQueueAppender // 內(nèi)存隊列
log4cpp::SyslogAppender // 本地syslog
log4cpp::Win32DebugAppender // 發(fā)送到缺省系統(tǒng)調(diào)試器
log4cpp::NTEventLogAppender // 發(fā)送到win 事件日志
2.設(shè)置日志輸出的格式
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函數(shù)strftime相同的語法,只是增加了1個。加號是以毫秒為單位的說明符%l,用 0填充為3位數(shù)字;
- %m - 你要輸出的日志信息;
- %n - 換行符;
- %p - 優(yōu)先級;
- %r - 該布局創(chuàng)建后的毫秒數(shù);
- %R - 從1970年1月1日0時開始到目前為止的秒數(shù);
- %u - 進程開始到目前為止的時鐘周期數(shù);
- %x - the NDC;
- %t - 線程的名字;
- 默認情況下,PatternLayout的ConversionPattern設(shè)置為“%m%n”。
3. 設(shè)置日志的輸出優(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官網(wǎng):


下載后解壓進入msvc10


因為官方提供的是vs2010編譯的項目,所以根據(jù)自己電腦裝的vs去打開即可,例如我這里使用vs2017去打開,打開后會提示升級,升級即可。

2. 編譯

3. 報錯解決1
不出意外的話,會報錯。
解決方法:①在log4cpp項目工程中找到NTEventLogCategories.mc文件,選擇該文件上然后右鍵選擇屬性,在彈出窗口中找到“配置屬性 - 自定義生成工具 - 常規(guī) - 命令行”中修改編譯命令,設(shè)置為如下命令:
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函數(shù)沖突,所以需要設(shè)置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); // 設(shè)置自定義布局
// 輸出日志的操作類
log4cpp::Category& logCat = log4cpp::Category::getInstance("logCat");
logCat.addAppender(logFile);
//設(shè)置優(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";
}
// 關(guān)閉日志
log4cpp::Category::shutdown();
return 0;
}三、Linux
1. 下載Log4cpp
可以通過上面的官網(wǎng)去下載,然后再拷入Linux系統(tǒng)中!
或者根據(jù)自己系統(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); // 設(shè)置自定義布局
// 輸出日志的操作類
log4cpp::Category& logCat = log4cpp::Category::getInstance("logCat");
logCat.addAppender(logFile);
//設(shè)置優(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";
}
// 關(guān)閉日志
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函數(shù)同級目錄了。
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
# 回卷日志個數(shù)名
log4cpp.appender.RootLog.fileNamePattern = test_%i.log
# 日志個數(shù)
log4cpp.appender.RootLog.maxBackupIndex = 256
# append=true 信息追加到上面指定的日志文件中,false表示將信息覆蓋指定文件內(nèi)容
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)日志寫入
};
/* 宏定義,方便調(diào)用 */
#define LOG_DEBUG MyLogger::instance()->GetHandle()->debug // 調(diào)試
#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__ : 函數(shù)名字。
*/
#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函數(shù)測試
#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";
// 關(guān)閉日志
log4cpp::Category::shutdown();
return 0;
}運行結(jié)果:

在運行一次項目:

Linux編譯命令:(鏈接的是靜態(tài)庫)
g++ main.cpp MyLogger.h MyLogger.cpp -std=c++11 -I ./inlcude/ -L ./lib/ -llog4cpp1 -lpthread -o test_log4cpp
2. 純代碼使用log4cpp
網(wǎng)上找的代碼,感覺挺不錯的,拷貝過來做了修改,改成自己以后做項目可能會這樣使用!
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; // 本地文件
/*采用單例模式設(shè)計,包含兩個category對象,一個負責輸出到屏幕的信息,一個負責記錄到日志的信息,
通過設(shè)置優(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);
//獲取日志函數(shù),默認參數(shù)選擇是否輸出到屏幕
static MyLog* getLog(bool toScreen = false);
//銷毀日志對象
static void destoryLog();
//設(shè)置日志記錄優(yōu)先級
static void setPri(log4cpp::Priority::PriorityLevel coutLevel, log4cpp::Priority::PriorityLevel logLevel);
//記錄日志,調(diào)用參數(shù) __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");
};
//為避免每次調(diào)用都要填寫參數(shù)__LINE__和__FUNCTION__,可以使用帶參數(shù)的宏定義
#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__);
#endifMyLog.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) {
// 判斷如果傳入文件名參數(shù)為空,或為默認參數(shù),則使用當前年月日.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個回卷
//設(shè)置布局
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);
//設(shè)置優(yōu)先級
MyLog::logCat.setPriority(MyLog::logPri);
MyLog::coutCat.setPriority(MyLog::coutPri);
}
MyLog::log->outToScreen = toScreen;
return true;
}
//獲取日志函數(shù),默認參數(shù)選擇是否輸出到屏幕
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;
}
//設(shè)置日志記錄優(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);
}
//記錄日志,調(diào)用參數(shù)__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函數(shù)測試
#include "MyLog.h"
int main(void) {
if (!MyLog::init("")) {
fprintf(stderr, "init log module failed.\n");
return -1;
}
MyLogWARN("警告");
MyLogINFO("信息");
MyLogERROR("錯誤");
MyLogDEBUG("調(diào)試");
// 關(guān)閉日志
log4cpp::Category::shutdown();
return 0;
}運行結(jié)果:

Linux編譯命令:(鏈接的是靜態(tài)庫)
g++ main.cpp MyLog.h MyLog.cpp -std=c++11 -I ./inlcude/ -L ./lib/ -llog4cpp1 -lpthread -o test_log4cpp
五、總結(jié)
日志在項目中是必須使用的,如果看完此篇博客還是不太懂log4cpp日志如何使用,直接拷貝上面項目代碼去到自己的項目中就可以直接使用了!
到此這篇關(guān)于C++ Log4cpp跨平臺日志庫使用記錄(Window與Linux)的文章就介紹到這了,更多相關(guān)C++ Log4cpp內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Qt音視頻開發(fā)之音頻播放QAudioOutput的實現(xiàn)
這篇文章主要為大家詳細介紹了如何利用Qt實現(xiàn)音頻播放QAudioOutput功能,文中的示例代碼講解詳細,對我們學習Qt開發(fā)有一定的幫助,需要的可以參考一下2023-03-03
C++?BoostAsyncSocket實現(xiàn)異步反彈通信的案例詳解
這篇文章主要為大家詳細介紹了C++?BoostAsyncSocket如何實現(xiàn)異步反彈通信,文中的示例代碼講解詳細,具有一定的學習價值,感興趣的可以了解一下2023-03-03
C++編程模板匹配超詳細的識別手寫數(shù)字實現(xiàn)示例
大家好!本篇文章是關(guān)于手寫數(shù)字識別的,接下來我將在這里記錄我的手寫數(shù)字識別的從零到有,我在這里把我自己的寫代碼過程發(fā)出來,希望能幫到和我一樣努力求知的人2021-10-10
C++11/14 線程調(diào)用類對象和線程傳參的方法
這篇文章主要介紹了C++11/14 線程調(diào)用類對象和線程傳參的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-01-01

