1. 程式人生 > >C++:日誌庫log4cplus 2.0的使用說明

C++:日誌庫log4cplus 2.0的使用說明

以前在做java開發時一直都在用log4j,它配置靈活,功能強大。如果C++中也存在類似配置的日誌庫,則可以省去不少學習的時間。在C++中的確有這樣的一些庫,本文就拿其中用的最多的log4cplus來講講如何使用它。

可以從以上兩個地址中下載最新的檔案,本文使用的最新版本是log4cplus-2.0.2。下載完成並解壓後,可以在log4cplus-2.0.2目錄下找到msvc14目錄,進入後找到log4cplus.sln檔案。先在確認已Visual Studio 2015以上版本,然後雙擊開啟此檔案,就會看到如下內容:

其中,log4cplus可以生成動態庫,log4cplusS可以生成靜態庫。本文要在64位系統中生成測試用的靜態庫,所以配置成Debug x64,字符集設定成Unicode。然後編譯log4cplusS,會在msvc14\x64\bin.Debug下生成log4cplusSD.lib檔案。

下面是測試程式碼:

#include <vector>
#include <thread>
#include <chrono>
#include <string>
#include <memory>
#include <ctime>
#include <iomanip>

#include <log4cplus/logger.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/configurator.h>
#include <log4cplus/initializer.h>
#include <log4cplus/loglevel.h>
#include <log4cplus/ndc.h>

using namespace std;
using std::chrono::system_clock;

using namespace log4cplus;
using namespace log4cplus::helpers;

string getTime() {
	system_clock::time_point tp = system_clock::now();
	time_t raw_time = system_clock::to_time_t(tp);
	struct tm  *timeinfo = std::localtime(&raw_time);

	std::stringstream ss;
	ss << std::put_time(timeinfo, "%Y-%m-%d %H:%M:%S");

	return ss.str();
}

void doTestRun(int i) {
	static log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("main"));

	string threadName = "doRun-" + to_string(i);
	// 使用NDC給執行緒設定名稱
	log4cplus::NDCContextCreator _ndc(LOG4CPLUS_STRING_TO_TSTRING(threadName));

	while (true) {
		this_thread::sleep_for(3s);
		// 如果不加u8,日誌檔案會是GB2312格式
		string info = u8"你好:" + getTime();

		LOG4CPLUS_WARN(logger, LOG4CPLUS_STRING_TO_TSTRING(info));
	}
}

int main() {
	log4cplus::Initializer initializer;
	PropertyConfigurator pc(LOG4CPLUS_TEXT("log4cplus.properties"));
	pc.configure();

	vector<std::thread> threadVector;

	for (int i = 0; i < 5; i++) {
		threadVector.emplace_back(doTestRun, i);
	}

	for (vector<std::thread>::iterator itr = threadVector.begin(); itr != threadVector.end(); itr++) {
		itr->join();
	}

	return 0;
}

配置檔案log4cplus.properties中的內容:

log4cplus.rootLogger=DEBUG, STDOUT

log4cplus.appender.STDOUT=log4cplus::ConsoleAppender
log4cplus.appender.STDOUT.layout=log4cplus::TTCCLayout

# 對ALL_MSGS使用非同步Appender
log4cplus.appender.ALL_MSGS=log4cplus::AsyncAppender
# 非同步Appender的佇列大小
log4cplus.appender.ALL_MSGS.QueueLimit=10000
# 非同步Appender中具體使用RollingFileAppender作為寫檔案的FileAppender
log4cplus.appender.ALL_MSGS.Appender=log4cplus::DailyRollingFileAppender
# 應用重新啟動後是要清空日誌檔案再寫入,還是要接在日誌檔案後面接著寫入
log4cplus.appender.ALL_MSGS.Appender.Append=false
# 設定FileAppender的快取大小
log4cplus.appender.ALL_MSGS.Appender.BufferSize=10000
# 達到快取上限後是否立即寫入
log4cplus.appender.ALL_MSGS.Appender.ImmediateFlush=true
# 寫的檔案路徑和檔名
log4cplus.appender.ALL_MSGS.Appender.File=d:/Temp/test.log
# 設定每個日誌檔案的最大容量
log4cplus.appender.ALL_MSGS.Appender.MaxFileSize=250KB
# 日誌檔案達到最大容量後,重新命名檔案以備份,設定最大備份日誌檔案數
log4cplus.appender.ALL_MSGS.Appender.MaxBackupIndex=10
# 指定日誌檔案回滾週期
log4cplus.appender.ALL_MSGS.Appender.Schedule=MINUTELY
# 當日志文件達到回滾週期時,則重新生成新的日誌檔案,舊的日誌檔案會加上.%Y%m%d_%H%M字尾
log4cplus.appender.ALL_MSGS.Appender.DatePattern=%Y%m%d_%H%M
# 設定輸出使用的locale
# log4cplus.appender.ALL_MSGS.Appender.Locale=en_US.UTF-8
# 自定義FileAppender的輸出格式
log4cplus.appender.ALL_MSGS.Appender.layout=log4cplus::PatternLayout
# 自定義FileAppender的輸出格式的樣式
log4cplus.appender.ALL_MSGS.Appender.layout.ConversionPattern=%D{%Y-%m-%d %H:%M:%S.%q}%5p[%5t|%x][%l][%c]- %m%n


# category為main的日誌
log4cplus.logger.main=DEBUG, ALL_MSGS
log4cplus.additivity.main=false

程式碼執行結果儲存為UTF-8格式:

2018-10-18 18:41:00.898 WARN[29816|doRun-3][d:\vc_projects\log4cplus.cpp:45][main]- 你好:2018-10-18 18:41:00
2018-10-18 18:41:00.902 WARN[18180|doRun-4][d:\vc_projects\log4cplus.cpp:45][main]- 你好:2018-10-18 18:41:00
2018-10-18 18:41:00.902 WARN[17704|doRun-0][d:\vc_projects\log4cplus.cpp:45][main]- 你好:2018-10-18 18:41:00
2018-10-18 18:41:00.904 WARN[28388|doRun-2][d:\vc_projects\log4cplus.cpp:45][main]- 你好:2018-10-18 18:41:00
2018-10-18 18:41:00.905 WARN[  5164|doRun-1][d:\vc_projects\log4cplus.cpp:45][main]- 你好:2018-10-18 18:41:00

在程式碼中通過NDC給每個新建立的執行緒設定了執行緒名,這樣通過%x和%t可以在日誌中同時打印出執行緒名和執行緒編號。

log4cplus是通過如下的巨集生成日誌的:

    LOG4CPLUS_TRACE (logger, "printMessages()");
    LOG4CPLUS_DEBUG (logger, "This is a DEBUG message");
    LOG4CPLUS_INFO (logger, "This is a INFO message");
    LOG4CPLUS_WARN (logger, "This is a WARN message");
    LOG4CPLUS_ERROR (logger, "This is a ERROR message");
    LOG4CPLUS_FATAL (logger, "This is a FATAL message");

另外,需要注意才下幾點:
1.列印字串常量要使用LOG4CPLUS_TEXT,列印string要使用LOG4CPLUS_STRING_TO_TSTRING。
2.編譯程式碼時要使用Unicode字符集。
3.使用thread建立的執行緒只有執行緒編號,沒有執行緒名,可以使用NDC給執行緒設定一個名字,這樣檢視日誌時方便。

參考文件