最新要闻
- 欧联杯:塞维利亚胜尤文图斯
- 当前播报:印度:我们的智能手机取得极大成功!苹果等加大布局 曾称接下来靠他们
- 曝iPhone 15 Plus影像升级为4800万像素:但因良率问题量产延期 今日最新
- 全球热点!荣耀90系列屏幕升级:首发3840Hz零风险调光护眼屏
- 环球速讯:53°飞天遭哄抢 茅台自营电商i茅台用户超4000万:销售230亿
- 1900万没了!一梅赛德斯AMG ONE运输途中被烧成焦炭:原因未明_热消息
- 海通国际发布先导智能研报
- 当前快播:睡觉时枕边有手机会得脑瘤吗?网友吵翻:没明确答案 你怎么看?
- 纯白机身 颜值天花板!魅族20告白礼盒上架:3199元起_世界今头条
- 王小川:10年后机器智慧会超过人类 AI迭代周期成倍递减
- 并非“大更新”?消息称Win11 23H2仅基于22H2优化改进
- 每日时讯!焦点科技李磊:小语种覆盖全球超5万亿美元的市场
- 环球今日报丨360浏览器修改主页不会动_360浏览器修改主页
- 你会买吗?一块京A摩托车牌照价格涨破50万:揭秘为何要这么贵?-天天快播
- 医生用一根针帮患癌老人冻死肿瘤 网友称神奇:以为是中医针灸
- 生理期可以喝普洱茶吗_生理期有绝对禁忌事项吗_快消息
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
Qt+QtWebApp开发笔记(二):http服务器日志系统介绍、添加日志系统至Demo测试
前言
上一篇使用QtWebApp的基于Qt的轻量级http服务器实现了一个静态网页返回的Demo,网页服务器很重要的就是日志,因为在服务器类上并没有直接返回,所以,本篇先把日志加上。
(资料图片)
Demo
下载地址
链接:https://pan.baidu.com/s/1BPVRLS07qk-WPi-txERKbg?pwd=1234
日志系统
生产环境需要查看旧的日志消息,例如两天前的日志消息。
可以简单地将输出重定向到一个文件(MyFirstWebApp>logfile.txt),但这有两个问题:
- 在许多系统上,输出重定向有些慢。
- 日志文件将变得无限大,如果不短时间停止web服务器,就无法防止这种情况发生。
因此,最好让web服务器自己将所有消息写入文件。这就是记录器模块的作用。 要将日志模块的源代码包括到项目中,请在项目文件中添加一行:
include(../QtWebApp/QtWebApp/logging/logging.pri)
这个而模块也是QtWebApp的logging模块,如下: 然后在程序的*.ini文件中添加另一个部分:
[logging]minLevel=WARNINGbufferSize=100fileName=../logs/webapp1.logmaxSize=1000000maxBackups=2timestampFormat=dd.MM.yyyy hh:mm:ss.zzzmsgFormat={timestamp} {typeNr} {type} {thread} {msg}
日志级别有:DEBUG(别名ALL)、INFO、WARN或WARNING、CRITICAL(别名ERROR)、FATAL。信息级别由Qt 5.5引入。 上面的示例配置启用线程本地缓冲区,**这些缓冲区将不太重要的消息保留在内存中,直到出现警告或严重错误。**然后,错误消息与收集到的低级消息一起写入日志文件。只要一切正常,使用缓冲区可以大大减少日志文件的大小。像这样的系统操作员。 但是,缓冲区的内存和性能成本都很高。收益通常大于成本。要禁用缓冲区,请将bufferSize设置为0。在这种情况下,只有配置了minLevel及以上级别的消息才会写入日志文件。 如果没有指定文件名,则记录器会写入控制台。日志文件的路径可以是绝对路径,也可以是相对于配置文件的文件夹的路径。maxSize参数限制日志文件的大小(以字节为单位)。当超过此限制时,记录器将启动一个新文件。设置maxBackups指定磁盘上应保留多少旧日志文件。 时间戳格式设置的作用。QDateTime::toString()的文档以获得对字符的解释,还有更多可用的内容。msgFormat设置指定每条消息的格式。以下字段可用:
- {timestamp}:创建日期和时间
- {typeNr}:数字格式的消息类型或级别(0=DEBUG, 4=INFO, 1=WARNING, 2=CRITICAL, 3=FATAL)
- {type}:字符串格式的消息类型或级别(DEBUG, INFO, WARNING, CRITICAL, FATAL)
- {thread}:线程的ID号
- {msg}:消息文本
- {xxx}:可以自己定义的任何记录器变量QT 5.0及更新版本在调试模式下有一些附加变量:
{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开发人员将这三个字段添加到他们的框架中。也可以使用\n在消息格式中插入换行符和插入 制表符。上述所有变量也可以在日志消息中使用,例如:
qCritical("An error occured in {file}: out of disk space");
需要一个指向FileLogger实例的全局指针,以便整个程序都可以访问它。首先添加到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的实例:
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();}
数字10000是以毫秒为单位的刷新间隔,记录器使用它来重新加载配置文件。因此,可以在程序运行时编辑任何记录器设置,并且更改在几秒钟后生效,而无需重新启动服务器。如果不希望自动重新加载,请使用值0。 给了一个示例代码,用于查询和记录库的版本号。一些人要求添加该功能。不要忘记创建一个空文件夹MyFirstWebApp/logs。记录器本身不会创建文件夹。 现在可以启动应用程序并查看会发生什么。因为程序没有错误,所以日志文件保持为空。但 可以看到控制台窗口中的输出已降至最低:
让在logincontroller.cpp中插入一条qCritical()消息,然后可以看到日志缓冲区工作: 然后打开URLhttp://localhost:8080/login?username=test&password=wrong. 再次查看日志文件,它就在那里:
现在通过将min Level降低到DEBUG来进行另一个测试。保存ini文件,等待10秒,然后打开URLhttp://localhost:8080/hello.再次检查日志文件。可以看到,尽管没有发生错误,但现在所有的调试消息都已写入。因此,在不重新启动程序的情况下更改日志级别可以很好地工作。
其实这个很容易看出来,是直接对qt的几个日志等级进行了(PS:这个日志库还不错,installMsgHandler可以截断qDebug等相关的错误信息,可以直接无缝使用到每一个qt项目中,有这个兴趣可以试一试)。
记录器变量
写到记录器支持用户定义的变量。这些变量是线程本地的,在清除它们之前一直保留在内存中。对于web应用程序,在每条消息中记录当前用户的名称可能很有用。向requestmapper.cpp添加代码以设置记录器变量:
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); ...}
通过这种方式,请求映射器在将请求传递给控制器类之前,为所有传入的HTTP请求查询调用用户的名称。 现在可以修改ini文件以使用该变量:
msgFormat={timestamp} {typeNr} {type} {thread} User:{currentUser} {msg}
运行程序并打开URLhttp://localhost:8080/login?username=test&password=hello两次。然后再次检查日志文件:
在用户登录之前,可以看到变量{currentUser}为空。然后,所有以下请求都会以该用户的名称记录。 注意:在RequestMapper类中放置了许多静态资源(logger、sessionStore、staticFileController、templateCache)。在实际应用程序中,建议创建一个单独的类,例如名称为“Globals”的类,这样每个人都知道在哪里可以找到这样的资源。或者按照在Demo1项目中的例子,将它们放在任何类之外的cpp源文件中。
日志缓冲区和线程池
由于线程被重新用于后续的HTTP请求,记录器可能会输出更多的细节。例如,假设第一个成功的HTTP请求会产生一些隐藏的调试消息,然后由同一线程处理的第二个请求会产生错误。然后,日志文件将包含错误消息以及所有缓冲的调试消息。但其中一些来自以前的HTTP请求,并不需要它。 要清除两个HTTP请求之间的缓冲区,请添加到requestmapper.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);}
因此,每当HTTP请求的处理完成时,都要清理记录器的内存。当同一个线程处理下一个请求时,它将以空缓冲区开始。(碰到错误则会输出到文件,所以一个http请求完成了,就是其前面的日志都是无错误,所以可以清空了)。
双文件记录器
该项目还包含一个DualFileLogger类,可用于并行生成两个日志文件。这可能对以下设置组合有用:
- 主记录日志文件
minLevel=INFObufferSize=0
- 第二日志文件
minLevel=ERROR (or WARNING)bufferSize=100
这样,主日志文件就不包含调试消息。但是,当发生错误时,辅助日志文件会包含该错误以及多达100条相关的调试消息。如果错误消息本身无法识别问题原因,则此文件特别有用。
总结
这个日志logging模块起到的最大作用,是因为在QtWebApp三方源码中的qDebug,qWarn,QFatal等相关系统直接输出到控制台的,使用该日志则截断才可以获取httpservice模块以及其他模块中的打印调试信息,而这些信息是在函数返回值中没有体现的。 为了能查看到三方模块日志,则必须要使用logging模块,或者自己写一个模块去截断,或者直接修改三方源码中的调试信息的代码。 使用httpservice肯定是最好使用logging模块了。
Demo增量:添加logging日志模块
步骤一:准备代码模板
准备之前的demo模板:
步骤二:拷贝logging模块
将QtWebApp中的logging,符合模块化设计准则,如下图:
拷贝到的Demo
添加模块进入工程:
# logging模块,QtWebApp自带的三方模块include ($$PWD/modules/logging/logging.pri)
第三方的模块。
步骤三:添加配置logging的配置文件
先把上一篇的Demo配置文件加了listener之后就读不出的问题解决了,其实区别关键在下面:
beginGroup就是进入了这一组,这一组拿到key就可以不带前缀。
然后开始添加日志配置,也在httpServerManager,因为配置文件beginGroup之后就是操作单独一组了,这里从第三方源码中也可以看出来:
本次加入logging,也要进行配置文件分组的区分,原来的_pSettings改成_pHttpListenerSettings,然后新增_pLoggingListenerSettings用于配置logging模块的配置实例:
步骤四:新增logging日志代码
步骤五:运行结果
至此,日志加入成功
步骤六:日志配置调整
修改下日志时间:
记录日志则是:
Demo源码
HttpServerManager.h
#ifndef HTTPSERVERMANAGER_H#define HTTPSERVERMANAGER_H#include #include #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; // 运行状态private: HttpListener *_pHttpListener; // http服务监听器 QSettings *_pHttpListenerSettings; // http服务器配置文件 FileLogger *_pFileLogger; // 日志记录 QSettings *_pFileLoggerSettings; // 日志配置文件private: QString _ip; // 服务器监听ip(若为空,则表示监听所有ip) quint16 _port; // 服务器监听端口 int _minThreads; // 空闲最小线程数 int _maxThreads; // 负载最大线程数 int _cleanupInterval; // 空线程清空间隔(单位:毫秒) int _readTimeout; // 保持连接空载超时时间(单位:毫秒) int _maxRequestSize; // 最大请求数 int _maxMultiPartSize; // 上载文件最大数(单位:字节)};#endif // HTTPSERVERMANAGER_H
HttpServerManager.cpp
#include "HttpServerManager.h"#include #include #include #include //#define LOG qDebug()<<__FILE__<<__LINE__//#define LOG qDebug()<<__FILE__<<__LINE__<<__FUNCTION__//#define LOG qDebug()<<__FILE__<<__LINE__<applicationDirPath()); LOG << httpServerPath << "exit:" << QFile::exists(httpServerPath); // 启动日志几里路 { if(!_pFileLoggerSettings) { _pFileLoggerSettings = new QSettings(httpServerPath, QSettings::IniFormat); } _pFileLoggerSettings->beginGroup("logging"); // 日志不会主动创建文件夹,这里需要补全 { 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(); } // 启动http的监听 { 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配置文件的相对路径
解决
关键词:
-
Qt+QtWebApp开发笔记(二):http服务器日志系统介绍、添加日志系统至Demo测试
前言上一篇使用QtWebApp的基于Qt的轻量级http服务器实现了一个静态网页返回的Demo,网页服务器很重要的就是
来源: Qt+QtWebApp开发笔记(二):http服务器日志系统介绍、添加日志系统至Demo测试
易基因:m5C高甲基化介导EGFR突变的非小细胞肺癌耐药潜在机理
焦点热讯:ipa文件怎么安装到iPhone手机上?
ipa文件怎么安装到iPhone手机上?
聊聊Seata分布式事务解决方案的AT模式_每日观察
科创板收盘播报:科创50指数涨0.52% 次新股表现活跃 全球视讯
欧联杯:塞维利亚胜尤文图斯
当前播报:印度:我们的智能手机取得极大成功!苹果等加大布局 曾称接下来靠他们
曝iPhone 15 Plus影像升级为4800万像素:但因良率问题量产延期 今日最新
全球热点!荣耀90系列屏幕升级:首发3840Hz零风险调光护眼屏
环球速讯:53°飞天遭哄抢 茅台自营电商i茅台用户超4000万:销售230亿
1900万没了!一梅赛德斯AMG ONE运输途中被烧成焦炭:原因未明_热消息
海通国际发布先导智能研报
Lerna 备忘清单_开发速查表分享
CF1512D Corrupted Array 题解 天天观点
全球实时:Blazor实战——Known框架快速开始
【解决方法】家用路由器的复位/重置(reset)操作,解决管理员后台密码遗忘
当前快播:睡觉时枕边有手机会得脑瘤吗?网友吵翻:没明确答案 你怎么看?
纯白机身 颜值天花板!魅族20告白礼盒上架:3199元起_世界今头条
王小川:10年后机器智慧会超过人类 AI迭代周期成倍递减
并非“大更新”?消息称Win11 23H2仅基于22H2优化改进
每日时讯!焦点科技李磊:小语种覆盖全球超5万亿美元的市场
测试管理快速入门
【天天新要闻】上海丨阿里云 Serverless 技术实战营邀你来玩!
环球今日报丨360浏览器修改主页不会动_360浏览器修改主页
你会买吗?一块京A摩托车牌照价格涨破50万:揭秘为何要这么贵?-天天快播
医生用一根针帮患癌老人冻死肿瘤 网友称神奇:以为是中医针灸
生理期可以喝普洱茶吗_生理期有绝对禁忌事项吗_快消息
Centos7 设置定时任务
泰国进口乳胶!网易严选乳胶垫、枕头大促:54元起
iQOO Pad搭载12.1英寸巨屏:2.8K分辨率、144Hz高刷 当前要闻
【世界聚看点】华为5倍薪酬再招天才少年!任正非:破题能力最重要 不是综合素质
当前视点!520用更好的长焦镜头表达爱意:华为P60 Pro长焦人像 让爱不分昼夜
华为新款家庭存储支持断电保护电源:停电自动关机、来电自动开机_世界球精选
观速讯丨2023中央财经大学在职课程培训班怎么样?
【GPT-4理论篇-1】GPT-4核心技术探秘
软件工程快速入门(下)-天天实时
环球热消息:聊聊分布式事务一致性与本地消息表
西门豹人物简介卡_西门豹人物简介
豹子闯入印度男子家中偷狗 狗主人惊醒淡定玩手机 网友:心真大
无限复制没了?《塞尔达传说:王国之泪》1.1.1更新发布:修复主线任务Bug_天天新动态
前高管唱衰:苹果MR设备将是史上最糟糕的产品之一 天天观天下
当前播报:裁员超千人后 长安福特又被曝裁减百万产能
曾致两死一伤!台州特斯拉事故歪曲事实视频作者致歉 全球独家
斗罗大陆剧场版最终预告公布,海神大战天使神,还有专属主题曲
通讯!软件工程快速入门
每日资讯:技术干货|如何利用 ChunJun 实现数据离线同步?
快看:腾讯云的devops自动化部署代替jenkins
双检锁(DCL)实现懒汉单例模式_全球讯息
网传云南一公园有多人用针扎小象,园方回应:已反馈了该情况,有关部门在协助调查
1199元起 雷蛇天狼星V2专业版游戏音箱发布:背投式RGB|当前最新
多芬广告呼吁女性游戏角色不必性感 宣传女性身材自信 引玩家众怒|世界热头条
openai为chatgpt人工智能推出ios应用
兑现“十年合约”:微软正式开启与NVIDIA合作
菜鸟CEO万霖发全员信:开启新创业征程 建设全球领先数智物流集团-天天热门
一机搞定全屋清洁!石头智能洗地机A10 Ultra图赏
日本4月份贸易赤字4324亿日元 信息
JS函数中的属性-全球简讯
【天天速看料】ET介绍——事件机制EventSystem
聊聊Sentinel的熔断降级
速讯:30多万买豪华行政车 新一代凯迪拉克CT6内饰官图:超帅9k曲面屏上车
《王者荣耀》520亚瑟新皮肤太过250:开局一条狗 玩家直呼要买
马克思主义理论专业大学排名(马克思主义专业大学排名及分数线)_世界最新
ChatGPT正式登陆iOS!但苹果却禁止员工使用-当前快报
科普:相机镜头的“放大倍率”是什么?
真我GT Neo5 SE“圣白幻影”配色亮相:颜值质感拉满|全球热推荐
项目管理快速入门
实时:聊聊Mybatis集成Spring的原理
SSM整合使用 天天信息
观速讯丨南微医学:5月18日融资买入1167.84万元,融资融券余额2.55亿元
华为凌霄子母路由Q6E开启预售:499元 每个房间都Wi-Fi满格
电动车价格战还打不打?电池级碳酸锂翻倍式触底反弹 重返30万元/吨 当前聚焦
网传云南一公园多人用针扎小象引围观 官方回应:网友呼吁不要再看动物表演
好消息!罗马后卫切利克赛后表示:我很好,伤势并不严重
JMeter性能测试工具快速入门教程
【读财报】4月猪价微降 上市猪企销量、收入环比变动较小
手机PC秒变16TB!华为家庭存储新款发布:再不怕断电了|焦点热议
当前热点-7.2万元 大疆发布Matrice 350 RTK旗舰无人机:升级20公里图传
算力达国际主流!飞腾国产服务器CPU腾云S2500被国家博物馆收藏 聚焦
接下来三十年还会继续快速贬值吗?-热点在线
学系统集成项目管理工程师(中项)系列22c_信息化知识(下)_环球即时看
重磅!ChatGPT正式发布App iOS客户端可下载
环球聚焦:Epic大特卖开启!7.5折套娃优惠券来了 超多大作打骨折
莒南县应急管理局全面部署五一期间应急值守工作
每日精选:ET介绍——C#更好的协程
全球快看:01-module/分频器/激励写法
全球动态:DDR2 学习笔记(一)
全球今日报丨女子帮摔倒老人反被指认为肇事者:本人正能量回应获网友点赞
今年夏天逃不掉高温了:全球平均气温正在波动上升 全球今头条
今亮点!员工回怼加班遭光速开除!公司回应:矛盾来源并不是加不加班
环球热门:跟苹果不一样!说到生产力 华为才是真正懂中国人的
全球今日讯!《猫和老鼠》才是永远的神!凭什么能碾压AI作画?
冲击欧联冠军!穆里尼奥第六次进入欧战决赛,前五次全胜
全球今头条!盂县气象局发布雷暴大风蓝色预警【Ⅳ级/一般】【2023-05-19】
天天热消息:人寿学平险保障范围_人寿学平险报销范围
斗鱼第一季度总净营收为14.831亿元 同期相比下滑17.4%
《王者荣耀》游戏官方推出女装品牌 限量的五款连衣裙均未售罄
美国蒙大拿州签署法案封禁TikTok 将于2024年1月份执行
Xbox或将推出全新商业模式 提供游戏片段试玩或带广告的免费游玩
因原材料与运输成本上涨 可口可乐或将上演“涨价大戏”