最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Qt+QtWebApp開發(fā)筆記(二):http服務(wù)器日志系統(tǒng)介紹、添加日志系統(tǒng)至Demo測(cè)試

2023-05-19 15:38 作者:紅胖子_AAA紅模仿  | 我要投稿

前言

??上一篇使用QtWebApp的基于Qt的輕量級(jí)http服務(wù)器實(shí)現(xiàn)了一個(gè)靜態(tài)網(wǎng)頁返回的Demo,網(wǎng)頁服務(wù)器很重要的就是日志,因?yàn)樵诜?wù)器類上并沒有直接返回,所以,本篇先把日志加上。

Demo

??

下載地址

??鏈接:https://pan.baidu.com/s/1BPVRLS07qk-WPi-txERKbg?pwd=1234

日志系統(tǒng)

生產(chǎn)環(huán)境需要查看舊的日志消息,例如兩天前的日志消息。

??可以簡(jiǎn)單地將輸出重定向到一個(gè)文件(MyFirstWebApp>logfile.txt),但這有兩個(gè)問題:

  • 在許多系統(tǒng)上,輸出重定向有些慢。

  • 日志文件將變得無限大,如果不短時(shí)間停止web服務(wù)器,就無法防止這種情況發(fā)生。

??因此,最好讓web服務(wù)器自己將所有消息寫入文件。這就是記錄器模塊的作用。
??要將日志模塊的源代碼包括到項(xiàng)目中,請(qǐng)?jiān)陧?xiàng)目文件中添加一行:

include(../QtWebApp/QtWebApp/logging/logging.pri)

??這個(gè)而模塊也是QtWebApp的logging模塊,如下:
??


??然后在程序的*.ini文件中添加另一個(gè)部分:

[logging]minLevel=WARNING bufferSize=100fileName=../logs/webapp1.log maxSize=1000000maxBackups=2timestampFormat=dd.MM.yyyy hh:mm:ss.zzz msgFormat={timestamp} {typeNr} {type} {thread} {msg}

??日志級(jí)別有:DEBUG(別名ALL)、INFO、WARN或WARNING、CRITICAL(別名ERROR)、FATAL。信息級(jí)別由Qt 5.5引入。
??上面的示例配置啟用線程本地緩沖區(qū),**這些緩沖區(qū)將不太重要的消息保留在內(nèi)存中,直到出現(xiàn)警告或嚴(yán)重錯(cuò)誤。**然后,錯(cuò)誤消息與收集到的低級(jí)消息一起寫入日志文件。只要一切正常,使用緩沖區(qū)可以大大減少日志文件的大小。像這樣的系統(tǒng)操作員。
??但是,緩沖區(qū)的內(nèi)存和性能成本都很高。收益通常大于成本。要禁用緩沖區(qū),請(qǐng)將bufferSize設(shè)置為0。在這種情況下,只有配置了minLevel及以上級(jí)別的消息才會(huì)寫入日志文件。
??如果沒有指定文件名,則記錄器會(huì)寫入控制臺(tái)。日志文件的路徑可以是絕對(duì)路徑,也可以是相對(duì)于配置文件的文件夾的路徑。maxSize參數(shù)限制日志文件的大?。ㄒ宰止?jié)為單位)。當(dāng)超過此限制時(shí),記錄器將啟動(dòng)一個(gè)新文件。設(shè)置maxBackups指定磁盤上應(yīng)保留多少舊日志文件。
??時(shí)間戳格式設(shè)置的作用。QDateTime::toString()的文檔以獲得對(duì)字符的解釋,還有更多可用的內(nèi)容。msgFormat設(shè)置指定每條消息的格式。以下字段可用:

  • {timestamp}:創(chuàng)建日期和時(shí)間

  • {typeNr}:數(shù)字格式的消息類型或級(jí)別(0=DEBUG, 4=INFO, 1=WARNING, 2=CRITICAL, 3=FATAL)

  • {type}:字符串格式的消息類型或級(jí)別(DEBUG, INFO, WARNING, CRITICAL, FATAL)

  • {thread}:線程的ID號(hào)

  • {msg}:消息文本

  • {xxx}:可以自己定義的任何記錄器變量QT 5.0及更新版本在調(diào)試模式下有一些附加變量:

{file}:Filename of source code where the message was generated{function}:Function where the message was generated{line}:Line number where the message was generated

??Qt開發(fā)人員將這三個(gè)字段添加到他們的框架中。也可以使用\n在消息格式中插入換行符和插入??制表符。上述所有變量也可以在日志消息中使用,例如:

qCritical("An error occured in {file}: out of disk space");

??需要一個(gè)指向FileLogger實(shí)例的全局指針,以便整個(gè)程序都可以訪問它。首先添加到global.h:

#include "httpsessionstore.h"#include "staticfilecontroller.h"#include "templatecache.h"#include "filelogger.h"using namespace stefanfrings;/** Storage for session cookies */extern HttpSessionStore* sessionStore;/** Controller for static files */extern StaticFileController* staticFileController;/** Cache for template files */extern TemplateCache* templateCache;/** Redirects log messages to a file */extern FileLogger* logger;#endif // GLOBAL_H

??global.cpp:

#include "global.h"HttpSessionStore* sessionStore;StaticFileController* staticFileController;TemplateCache* templateCache;FileLogger* logger;

??在main.cpp中,配置FileLogger的實(shí)例:

int main(int argc, char *argv[]){ ? ?QCoreApplication app(argc, argv); ? ?QString configFileName=searchConfigFile(); ? ?// Configure logging ? ?QSettings* logSettings=new QSettings(configFileName,QSettings::IniFormat,&app); ? ?logSettings->beginGroup("logging"); ? ?logger=new FileLogger(logSettings,10000,&app); ? ?logger->installMsgHandler(); ? ?// Log the library version ? ?qDebug("QtWebApp has version %s",getQtWebAppLibVersion()); ? ?// Session store ? ?QSettings* sessionSettings=new QSettings(configFileName,QSettings::IniFormat,&app); ? ?sessionSettings->beginGroup("sessions"); ? ?sessionStore=new HttpSessionStore(sessionSettings,&app); ? ?// Static file controller ? ?QSettings* fileSettings=new QSettings(configFileName,QSettings::IniFormat,&app); ? ?fileSettings->beginGroup("files"); ? ?staticFileController=new StaticFileController(fileSettings,&app); ? ?// Configure template cache ? ?QSettings* templateSettings=new QSettings(configFileName,QSettings::IniFormat,&app); ? ?templateSettings->beginGroup("templates"); ? ?templateCache=new TemplateCache(templateSettings,&app); ? ?// HTTP server ? ?QSettings* listenerSettings=new QSettings(configFileName,QSettings::IniFormat,&app); ? ?listenerSettings->beginGroup("listener"); ? ?new HttpListener(listenerSettings,new RequestMapper(&app),&app); ? ?return app.exec();}

??數(shù)字10000是以毫秒為單位的刷新間隔,記錄器使用它來重新加載配置文件。因此,可以在程序運(yùn)行時(shí)編輯任何記錄器設(shè)置,并且更改在幾秒鐘后生效,而無需重新啟動(dòng)服務(wù)器。如果不希望自動(dòng)重新加載,請(qǐng)使用值0。
??給了一個(gè)示例代碼,用于查詢和記錄庫(kù)的版本號(hào)。一些人要求添加該功能。
不要忘記創(chuàng)建一個(gè)空文件夾MyFirstWebApp/logs。記錄器本身不會(huì)創(chuàng)建文件夾。
??現(xiàn)在可以啟動(dòng)應(yīng)用程序并查看會(huì)發(fā)生什么。因?yàn)槌绦驔]有錯(cuò)誤,所以日志文件保持為空。但??可以看到控制臺(tái)窗口中的輸出已降至最低:
??

??讓在logincontroller.cpp中插入一條qCritical()消息,然后可以看到日志緩沖區(qū)工作:
??然后打開URLhttp://localhost:8080/login?username=test&password=wrong.
??再次查看日志文件,它就在那里:
??

??現(xiàn)在通過將min Level降低到DEBUG來進(jìn)行另一個(gè)測(cè)試。保存ini文件,等待10秒,然后打開URLhttp://localhost:8080/hello.再次檢查日志文件??梢钥吹?,盡管沒有發(fā)生錯(cuò)誤,但現(xiàn)在所有的調(diào)試消息都已寫入。因此,在不重新啟動(dòng)程序的情況下更改日志級(jí)別可以很好地工作。
??

??其實(shí)這個(gè)很容易看出來,是直接對(duì)qt的幾個(gè)日志等級(jí)進(jìn)行了(PS:這個(gè)日志庫(kù)還不錯(cuò),installMsgHandler可以截?cái)鄎Debug等相關(guān)的錯(cuò)誤信息,可以直接無縫使用到每一個(gè)qt項(xiàng)目中,有這個(gè)興趣可以試一試)。
??

記錄器變量

??寫到記錄器支持用戶定義的變量。這些變量是線程本地的,在清除它們之前一直保留在內(nèi)存中。對(duì)于web應(yīng)用程序,在每條消息中記錄當(dāng)前用戶的名稱可能很有用。向requestmapper.cpp添加代碼以設(shè)置記錄器變量:

void RequestMapper::service(HttpRequest& request, HttpResponse& response) { ? ?QByteArray path=request.getPath(); ? ?qDebug("RequestMapper: path=%s",path.data()); ? ?HttpSession session=sessionStore->getSession(request,response,false); ? ?QString username=session.get("username").toString(); ? ?logger->set("currentUser",username); ? ?...}

??通過這種方式,請(qǐng)求映射器在將請(qǐng)求傳遞給控制器類之前,為所有傳入的HTTP請(qǐng)求查詢調(diào)用用戶的名稱。
??現(xiàn)在可以修改ini文件以使用該變量:

msgFormat={timestamp} {typeNr} {type} {thread} User:{currentUser} {msg}

??運(yùn)行程序并打開URLhttp://localhost:8080/login?username=test&password=hello兩次。然后再次檢查日志文件:
??

??在用戶登錄之前,可以看到變量{currentUser}為空。然后,所有以下請(qǐng)求都會(huì)以該用戶的名稱記錄。
??注意:在RequestMapper類中放置了許多靜態(tài)資源(logger、sessionStore、staticFileController、templateCache)。在實(shí)際應(yīng)用程序中,建議創(chuàng)建一個(gè)單獨(dú)的類,例如名稱為“Globals”的類,這樣每個(gè)人都知道在哪里可以找到這樣的資源?;蛘甙凑赵贒emo1項(xiàng)目中的例子,將它們放在任何類之外的cpp源文件中。

日志緩沖區(qū)和線程池

??由于線程被重新用于后續(xù)的HTTP請(qǐng)求,記錄器可能會(huì)輸出更多的細(xì)節(jié)。例如,假設(shè)第一個(gè)成功的HTTP請(qǐng)求會(huì)產(chǎn)生一些隱藏的調(diào)試消息,然后由同一線程處理的第二個(gè)請(qǐng)求會(huì)產(chǎn)生錯(cuò)誤。然后,日志文件將包含錯(cuò)誤消息以及所有緩沖的調(diào)試消息。但其中一些來自以前的HTTP請(qǐng)求,并不需要它。
??要清除兩個(gè)HTTP請(qǐng)求之間的緩沖區(qū),請(qǐng)?zhí)砑拥絩equestmapper.cpp:

void RequestMapper::service(HttpRequest& request, HttpResponse& response) { ? ?... ? ?else { ? ? ? ?response.setStatus(404,"Not found"); ? ? ? ?response.write("The URL is wrong, no such document."); ? ?} ? ?qDebug("RequestMapper: finished request"); ? ?logger->clear(true,true);}

??因此,每當(dāng)HTTP請(qǐng)求的處理完成時(shí),都要清理記錄器的內(nèi)存。當(dāng)同一個(gè)線程處理下一個(gè)請(qǐng)求時(shí),它將以空緩沖區(qū)開始。(碰到錯(cuò)誤則會(huì)輸出到文件,所以一個(gè)http請(qǐng)求完成了,就是其前面的日志都是無錯(cuò)誤,所以可以清空了)。

雙文件記錄器

??該項(xiàng)目還包含一個(gè)DualFileLogger類,可用于并行生成兩個(gè)日志文件。這可能對(duì)以下設(shè)置組合有用:

  • 主記錄日志文件

minLevel=INFObufferSize=0

  • 第二日志文件

minLevel=ERROR (or WARNING)bufferSize=100

??這樣,主日志文件就不包含調(diào)試消息。但是,當(dāng)發(fā)生錯(cuò)誤時(shí),輔助日志文件會(huì)包含該錯(cuò)誤以及多達(dá)100條相關(guān)的調(diào)試消息。如果錯(cuò)誤消息本身無法識(shí)別問題原因,則此文件特別有用。

總結(jié)

??這個(gè)日志logging模塊起到的最大作用,是因?yàn)樵赒tWebApp三方源碼中的qDebug,qWarn,QFatal等相關(guān)系統(tǒng)直接輸出到控制臺(tái)的,使用該日志則截?cái)嗖趴梢垣@取httpservice模塊以及其他模塊中的打印調(diào)試信息,而這些信息是在函數(shù)返回值中沒有體現(xiàn)的。
??為了能查看到三方模塊日志,則必須要使用logging模塊,或者自己寫一個(gè)模塊去截?cái)?,或者直接修改三方源碼中的調(diào)試信息的代碼。
??使用httpservice肯定是最好使用logging模塊了。

Demo增量:添加logging日志模塊

步驟一:準(zhǔn)備代碼模板

??準(zhǔn)備之前的demo模板:
??

步驟二:拷貝logging模塊

??將QtWebApp中的logging,符合模塊化設(shè)計(jì)準(zhǔn)則,如下圖:
??

??拷貝到的Demo
??

??添加模塊進(jìn)入工程:

# logging模塊,QtWebApp自帶的三方模塊include ($$PWD/modules/logging/logging.pri)

??


??第三方的模塊。

步驟三:添加配置logging的配置文件

??先把上一篇的Demo配置文件加了listener之后就讀不出的問題解決了,其實(shí)區(qū)別關(guān)鍵在下面:
??

??beginGroup就是進(jìn)入了這一組,這一組拿到key就可以不帶前綴。
??

??然后開始添加日志配置,也在httpServerManager,因?yàn)榕渲梦募eginGroup之后就是操作單獨(dú)一組了,這里從第三方源碼中也可以看出來:
??

??本次加入logging,也要進(jìn)行配置文件分組的區(qū)分,原來的_pSettings改成_pHttpListenerSettings,然后新增_pLoggingListenerSettings用于配置logging模塊的配置實(shí)例:

步驟四:新增logging日志代碼

??

??

??

步驟五:運(yùn)行結(jié)果

???


??至此,日志加入成功

步驟六:日志配置調(diào)整

??

??修改下日志時(shí)間:
??

?

記錄日志則是:
??

Demo源碼

HttpServerManager.h

#ifndef HTTPSERVERMANAGER_H#define HTTPSERVERMANAGER_H#include <QObject>#include <QMutex>#include "httplistener.h"#include "filelogger.h"#include "HelloWorldRequestHandler.h"class HttpServerManager : public QObject{ ? ?Q_OBJECTprivate: ? ?explicit HttpServerManager(QObject *parent = 0);public: ? ?static HttpServerManager *getInstance();public slots: ? ?void slot_start(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 開啟線程 ? ?void slot_stop(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 停止線程private: ? ?static HttpServerManager *_pInstance; ? ?static QMutex _mutex;private: ? ?bool _running; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 運(yùn)行狀態(tài)private: ? ?HttpListener *_pHttpListener; ? ? ? ? ? ? ? ? ? // http服務(wù)監(jiān)聽器 ? ?QSettings *_pHttpListenerSettings; ? ? ? ? ? ? ?// http服務(wù)器配置文件 ? ?FileLogger *_pFileLogger; ? ? ? ? ? ? ? ? ? ? ? // 日志記錄 ? ?QSettings *_pFileLoggerSettings; ? ? ? ? ? ? ? ?// 日志配置文件private: ? ?QString _ip; ? ? ? ? ? ? ? ?// 服務(wù)器監(jiān)聽ip(若為空,則表示監(jiān)聽所有ip) ? ?quint16 _port; ? ? ? ? ? ? ?// 服務(wù)器監(jiān)聽端口 ? ?int _minThreads; ? ? ? ? ? ?// 空閑最小線程數(shù) ? ?int _maxThreads; ? ? ? ? ? ?// 負(fù)載最大線程數(shù) ? ?int _cleanupInterval; ? ? ? // 空線程清空間隔(單位:毫秒) ? ?int _readTimeout; ? ? ? ? ? // 保持連接空載超時(shí)時(shí)間(單位:毫秒) ? ?int _maxRequestSize; ? ? ? ?// 最大請(qǐng)求數(shù) ? ?int _maxMultiPartSize; ? ? ?// 上載文件最大數(shù)(單位:字節(jié))};#endif // HTTPSERVERMANAGER_H

HttpServerManager.cpp

#include "HttpServerManager.h"#include <QApplication>#include <QDir>#include <QDebug>#include <QDateTime>//#define LOG qDebug()<<__FILE__<<__LINE__//#define LOG qDebug()<<__FILE__<<__LINE__<<__FUNCTION__//#define LOG qDebug()<<__FILE__<<__LINE__<<QThread()::currentThread()//#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd")#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")HttpServerManager *HttpServerManager::_pInstance = 0;QMutex HttpServerManager::_mutex;HttpServerManager::HttpServerManager(QObject *parent) ? ?: QObject(parent), ? ? ?_pHttpListener(0), ? ? ?_pHttpListenerSettings(0), ? ? ?_pFileLogger(0), ? ? ?_pFileLoggerSettings(0), ? ? ?_running(false), ? ? ?_port(8088), ? ? ?_minThreads(2), ? ? ?_maxThreads(10), ? ? ?_cleanupInterval(60000), ? ? ?_readTimeout(60000), ? ? ?_maxRequestSize(100), ? ? ?_maxMultiPartSize(1024*1024*1024){}HttpServerManager *HttpServerManager::getInstance(){ ? ?if(!_pInstance) ? ?{ ? ? ? ?QMutexLocker lock(&_mutex); ? ? ? ?if(!_pInstance) ? ? ? ?{ ? ? ? ? ? ?_pInstance = new HttpServerManager(); ? ? ? ?} ? ?} ? ?return _pInstance;}void HttpServerManager::slot_start(){ ? ?if(_running) ? ?{ ? ? ? ?LOG << "It's running!!!"; ? ? ? ?return; ? ?} ? ?_running = true; ? ?LOG << "Succeed to run"; ? ?QString httpServerPath = QString("%1/etc/httpServer.ini").arg(qApp->applicationDirPath()); ? ?LOG << httpServerPath << "exit:" << QFile::exists(httpServerPath); ? ?// 啟動(dòng)日志幾里路 ? ?{ ? ? ? ?if(!_pFileLoggerSettings) ? ? ? ?{ ? ? ? ? ? ?_pFileLoggerSettings = new QSettings(httpServerPath, QSettings::IniFormat); ? ? ? ?} ? ? ? ?_pFileLoggerSettings->beginGroup("logging"); ? ? ? ?// 日志不會(huì)主動(dòng)創(chuàng)建文件夾,這里需要補(bǔ)全 ? ? ? ?{ ? ? ? ? ? ?QFileInfo fileInfo(httpServerPath); ? ? ? ? ? ?QString dirPath = fileInfo.dir().absolutePath(); ? ? ? ? ? ?dirPath = QString("%1/%2") ? ? ? ? ? ? ? ? ? ?.arg(dirPath) ? ? ? ? ? ? ? ? ? ?.arg(_pFileLoggerSettings->value("fileName").toString()); ? ? ? ? ? ?dirPath = dirPath.mid(0, dirPath.lastIndexOf("/")); ? ? ? ? ? ?QDir dir; ? ? ? ? ? ?dir.mkpath(dirPath); ? ? ? ?} ? ? ? ?_pFileLogger = new FileLogger(_pFileLoggerSettings); ? ? ? ?_pFileLogger->installMsgHandler(); ? ?} ? ?// 啟動(dòng)http的監(jiān)聽 ? ?{ ? ? ? ?if(!_pHttpListenerSettings) ? ? ? ?{ ? ? ? ? ? ?_pHttpListenerSettings = new QSettings(httpServerPath, QSettings::IniFormat); ? ? ? ?} ? ? ? ?_pHttpListenerSettings->beginGroup("listener"); ? ? ? ?_pHttpListener = new HttpListener(_pHttpListenerSettings, new HelloWorldRequestHandler); ? ?} ? ?LOG;}void HttpServerManager::slot_stop(){ ? ?if(!_running) ? ?{ ? ? ? ?LOG <<"It's not running!!!"; ? ? ? ?return; ? ?} ? ?_running = false; ? ?LOG << "Succeed to stop";}

工程模板v1.1.0

??

入坑

入坑一:日志一直不出來

問題

??日志一直不出來

原因

??

??日志log文件的路徑是基于ini配置文件的相對(duì)路徑

解決

??


Qt+QtWebApp開發(fā)筆記(二):http服務(wù)器日志系統(tǒng)介紹、添加日志系統(tǒng)至Demo測(cè)試的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
隆尧县| 任丘市| 醴陵市| 特克斯县| 辉南县| 诸暨市| 新宁县| 塔城市| 保山市| 伊川县| 塔城市| 长兴县| 五指山市| 扎囊县| 右玉县| 江北区| 临泽县| 奈曼旗| 竹北市| 五指山市| 吉水县| 固原市| 淮阳县| 禄丰县| 五常市| 巴马| 上林县| 临泽县| 收藏| 翁牛特旗| 安康市| 日喀则市| 太原市| 兰州市| 马山县| 登封市| 孟津县| 永兴县| 抚顺市| 岳普湖县| 峡江县|