Qt轻量级日志库QsLog的使用
C加加下的日志庫有很多,如log4cpp、Easylogging++等,Qt下也有log4qt。
不過我們今天要說的是QsLog,它是一個基于Qt的輕量級開源日志庫。
git地址:https://github.com/victronenergy/QsLog
輕到什么程度,請看如下:
代碼文件就是這么點。花點時間閱讀一下,秒改造成你自己的私有輪子。
雖然輕量級,但是對于基本的日志功能需求還是夠用的。
特征
- 六個日志級別(從跟蹤到致命)
- 運行時可配置的日志級別閾值。
- 關閉日志記錄時的最小開銷。
- 支持多個目標,附帶文件和調試目標。
- 線程安全
- 支持現成的常見Qt類型的日志記錄。
- 小依賴:直接把它放到你的項目中。
接下來,我們研究下它都有哪些功能。
一、QsLog使用方式
1. 源碼集成
在你的工程中,直接包含QsLog.pri文件,進行源碼集成。
當然你也可以包含QsLog.pri后,編譯為xx.dll,在應用工程中去調用xx.dll。
2. 動態庫集成
編譯QsLogSharedLibrary.pro,生成動態鏈接庫QsLog2.dll,在你的工程中進行調用。
二、日志級別
支持六個日志級別,優先級從低到高依次為:Trace、Debug、Info、Warn、Error、Fatal、Off。如下:
enum Level {TraceLevel = 0,DebugLevel,InfoLevel,WarnLevel,ErrorLevel,FatalLevel,OffLevel };- Trace:跟蹤,最低等級的,用于打開所有日志記錄。
- Debug:調試,打印一些細粒度調試運行信息。
- Info:信息,打印粗粒度信息,突出強調程序的運行過程。打印一些感興趣或者重要的信息,可用于環境中輸出程序運行的一些重要信息,但不能濫用,避免打印過多日志。
- Warn:警告,表明會出現潛在錯誤的情形,有些信息不是錯誤信息,但是也要給程序員的一些提示。
- Error:錯誤,指出雖然發生錯誤,但仍然不影響系統的繼續運行。打印錯誤和異常信息。
- Fatal:致命的,發生嚴重錯誤,將導致應用程序的退出。這個級別比較高,程序直接停止運行了。
- Off:最高等級的,用于關閉所有日志記錄。
可以通過setLoggingLevel()設置記錄日志的級別。
void setLoggingLevel(Level newLevel)注意:
一般我們可以將日志級別保存到配置文件,以便程序發布后,可通過修改配置來改變記錄日志級別。
三、日志輸出目的地
QsLog的使用很簡單,在我們自己的工程中直接include它的QsLog.pri文件,然后源文件中包含QsLog.h就可以使用了。
1. 輸出到文件(支持文件分割)
// 測試文件為目的地 void test_output_file() {// 初始化日志機制Logger& logger = Logger::instance();logger.setLoggingLevel(QsLogging::TraceLevel);// 添加文件為目的地const QString sLogPath(QDir(QApplication::applicationDirPath()).filePath("log.txt"));DestinationPtr fileDestination(DestinationFactory::MakeFileDestination(sLogPath, EnableLogRotation, MaxSizeBytes(512*1024), MaxOldLogCount(5)));logger.addDestination(fileDestination);// 打印日志QLOG_TRACE() << "1-trace msg";QLOG_DEBUG() << "2-debug msg";QLOG_INFO() << "3-info msg";QLOG_WARN() << "4-warn msg";QLOG_ERROR() << "5-error msg";QLOG_FATAL() << "6-fatal msg";QsLogging::Logger::destroyInstance(); }-
代碼很簡單,setLoggingLevel()設置記錄的日志級別;
目前為TraceLevel,則日志級別比TraceLevel高的都會輸出到文件;
若為ErrorLevel,則只有"5-error msg"和"6-fatal msg"這2條會輸出。 -
然后設置文件名和輸出目的地。其中目的地是由DestinationFactory::MakeFileDestination()函數進行構造的,其原型為:
函數參數含義:
filePath: 日志文件名
rotation: 取值DisableLogRotation和EnableLogRotation,
前者表示禁止日志文件分割,即日志始終往一個文件中寫入。
后者表示啟用日志文件分割,此時sizeInBytesToRotateAfter和oldLogsToKeep參數才有意義。
sizeInBytesToRotateAfter: 每個日志文件的字節數大小限制,即到達此大小后,自動新建文件,在新文件中進行寫入。
oldLogsToKeep: 舊日志文件保留(備份)個數,超過此數量,自動刪除最久遠文件,備份文件最多支持10個。
若為2,則如下三個文件中內容,按照時間先后順序排列為:log.txt.2->log.txt.1->log.txt,在log.txt中為最新日志,log.txt.1為次新,log.txt.2為最久遠日志。
若此時log.txt超過sizeInBytesToRotateAfter限制,則會發生log.txt.2被刪除,log.txt.1被改名log.txt.2,log.txt被改名log.txt.1,新建log.txt。
運行效果:
2. 輸出到控制臺stdout
// 測試stdout為目的地 void test_output_stdout() {// 初始化日志機制Logger& logger = Logger::instance();logger.setLoggingLevel(QsLogging::TraceLevel);// 添加stdout為目的地DestinationPtr debugDestination(DestinationFactory::MakeDebugOutputDestination());logger.addDestination(debugDestination);// 打印日志QLOG_TRACE() << "1-trace msg";QLOG_DEBUG() << "2-debug msg";QLOG_INFO() << "3-info msg";QLOG_WARN() << "4-warn msg";QLOG_ERROR() << "5-error msg";QLOG_FATAL() << "6-fatal msg";QsLogging::Logger::destroyInstance(); }運行效果:
3. 輸出到處理函數
void logFunction(const QString &message, QsLogging::Level level) {qDebug() << "From log function: " << qPrintable(message) << " " << static_cast<int>(level); }// 測試函數為目的地 void test_output_function() {// 初始化日志機制Logger& logger = Logger::instance();logger.setLoggingLevel(QsLogging::TraceLevel);// 添加函數為目的地DestinationPtr functorDestination(DestinationFactory::MakeFunctorDestination(&logFunction));logger.addDestination(functorDestination);// 打印日志QLOG_TRACE() << "1-trace msg";QLOG_DEBUG() << "2-debug msg";QLOG_INFO() << "3-info msg";QLOG_WARN() << "4-warn msg";QLOG_ERROR() << "5-error msg";QLOG_FATAL() << "6-fatal msg";QsLogging::Logger::destroyInstance(); }輸出到函數,該函數需要定義為如下類型:
typedef void (*LogFunction)(const QString &message, Level level);運行效果:
4. 輸出到QTextEdit控件
除了上面的輸出方式,還可以輸出到一個QObject對象上,主要是通過信號槽機制,將打印日志發送到QObject的槽函數進行處理。
void MainWindow::writeLog(const QString &message, int level) {ui->textEdit->append(message + " " + QString::number(level)); } // 測試QObject為目的地 void test_output_qobject(MainWindow* window) {// 初始化日志機制Logger& logger = Logger::instance();logger.setLoggingLevel(QsLogging::TraceLevel);// 添加QObject為目的地DestinationPtr objectDestination(DestinationFactory::MakeFunctorDestination(window, SLOT(writeLog(QString,int))));logger.addDestination(objectDestination);// 打印日志QLOG_TRACE() << "1-trace msg";QLOG_DEBUG() << "2-debug msg";QLOG_INFO() << "3-info msg";QLOG_WARN() << "4-warn msg";QLOG_ERROR() << "5-error msg";QLOG_FATAL() << "6-fatal msg";QsLogging::Logger::destroyInstance(); }輸出到QObject時,需要定義其槽函數,為如下類型:
void xxxx(const QString &message, int level)寫本例子時,發現TRACE信息不能輸出到QObject,是因為QsLogDestFunctor.cpp文件中,write函數有個bug,如下:
void QsLogging::FunctorDestination::write(const QString &message, QsLogging::Level level) {if (mLogFunction)mLogFunction(message, level);if (level > QsLogging::TraceLevel)emit logMessageReady(message, static_cast<int>(level)); }應將>改為>=,修改后即可解決,如下:
void QsLogging::FunctorDestination::write(const QString &message, QsLogging::Level level) {if (mLogFunction)mLogFunction(message, level);if (level >= QsLogging::TraceLevel)emit logMessageReady(message, static_cast<int>(level)); }修改后的QsLog庫,下載鏈接:
https://download.csdn.net/download/u011832525/12520461
運行效果:
小結:
總結下,日志打印輸出目的地可以有4種,分別是:
- 輸出到文件;
- 輸出到控制臺stdout;
- 輸出到函數;
- 輸出到QObject。
并且可以添加任意多個目的地址,比如輸出到文件的同時,還要輸出到控制臺進行顯示,以方便查看調試打印信息。
四、打印源文件名稱和行號
在QsLog.pri文件中
DEFINES += QS_LOG_LINE_NUMBERS打開此宏定義,重新編譯,即可打印帶源文件名稱和行號的日志。如下:
運行效果:
五、禁止日志記錄
禁用日志記錄,有時候關閉日志記錄是有必要的。可以通過3種方式實現:
- 全局地,在編譯時,通過在QsLog.pri文件,打開DEFINES += QS_LOG_DISABLE宏定義。
- 全局地,在運行時,通過將日志級別設置為關閉,即setLoggingLevel(QsLogging::OffLevel)。
- 在編譯時,通過在目標文件中包含QsLogDisableForThisFile.h,為每個文件創建一個。
六、線程安全
使用日志宏進行打印日志是線程安全的,日志宏如下:
QLOG_TRACE() << "1-trace msg"; QLOG_DEBUG() << "2-debug msg"; QLOG_INFO() << "3-info msg"; QLOG_WARN() << "4-warn msg"; QLOG_ERROR() << "5-error msg"; QLOG_FATAL() << "6-fatal msg";這在前面我們已經使用過了。
如setLoggingLevel()、addDestination()函數不是線程安全的。
七、日志的異步打印
所謂的異步打印,其實就是單獨開一個線程來專門寫日志。
在QsLog.pri文件中
DEFINES += QS_LOG_SEPARATE_THREAD打開此宏定義,重新編譯,日志內容就會在單獨的線程中排隊并寫入。
八、總結
以下內容來自QsLog的git倉庫介紹:
QsLog is an easy to use logger that is based on Qt’s QDebug class. QsLog is released as open source, under the MIT license.
###Contribution policy### Bug fixes are welcome, larger changes however are not encouraged at this point due to the lack of time on my side for reviewing and integrating them. Your best bet in this case would be to open a ticket for your change or forking the project and implementing your change there, with the possibility of having it integrated in the future. All contributions will be credited, license of the contributions should be MIT.
意思就是有問題,歡迎提bug,不過我沒啥時間,修不修復就看我的心情了。如果你想玩,最好自己fork倉庫,以后,萬一未來哪天心情好了,想繼續迭代版本,你敲的代碼還是有可能merge進來的,到時候給你頒朵小紅花,不過要遵守老麻的許可噢!
看完本文后,有需要的客官大老爺,請自行斟酌。
若對你有幫助,歡迎點贊、收藏、評論,你的支持就是我的最大動力!!!
同時,阿超為大家準備了豐富的學習資料,歡迎關注公眾號“超哥學編程”,即可領取。
本文涉及工程代碼,公眾號回復:47QsLog,即可下載。
總結
以上是生活随笔為你收集整理的Qt轻量级日志库QsLog的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ES6学习笔记二arrow functi
- 下一篇: 根据xml文件找到对应的图片文件