96SEO 2026-02-19 19:35 5
Qt重定向QDebug自定义一个简易的日志管理类0.前言1.最简单的操作运行结果2.实现一个简易的日志管理类

QT日志模块的个性化使用格式化日志输出输出日志到文本日志输出对象信息
Qt/C开源作品39-日志输出增强版V2022($$$)一、前言二、主要功能三、效果图四、开源主页五、核心代码
原文链接https://blog.csdn.net/gongjianbo1992/article/details/108030391
qInstallMsgHandler(QtMsgHandler);在
qInstallMessageHandler(QtMessageHandler);返回的函数指针我们可以保存起来需要输出到控制台时进行调用。
file(log.txt);if(file.open(QIODevice::WriteOnly|QIODevice::Append)){QTextStream
stream(file);streammsgendl;file.close();}
{//设置重定向操作的函数qInstallMessageHandler(myMessageHandle);qDebug()Test
代码链接https://github.com/gongjianbo/SimpleQtLogger
{LogManager::getInstance()-initManager();//初始化QApplication
2.根据时间戳每天重新生成一个文件超过文件大小也会重新生成*/
{Q_OBJECTQ_DISABLE_COPY_MOVE(LogManager)LogManager();
QDateTimeLogManager::LogManager()
QCoreApplication::applicationDirPath()需要先实例化一个appif
qInstallMessageHandler(LogManager::outputHandler);
locker(logMutex);logFile.close();if
{qInstallMessageHandler(defaultOutput);defaultOutput
LogManager::setFileSizeLimit(qint64
LogManager::outputHandler(QtMsgType
转发给单例的成员函数LogManager::getInstance()-outputLog(type,
LogManager::outputLog(QtMsgType
QDateTime::currentDateTime().toString([yyyy-MM-dd
写入文件stream.setDevice(logFile);stream
cmd_text;stream.setString(cmd_text);switch
QDate::currentDate().addDays(1).startOfDay().toMSecsSinceEpoch();
先计算好下一次生成文件的时间点然后和当前进行比较这里没有考虑调节系统日期的情况if
QDateTime::currentDateTime().toMSecsSinceEpoch()){logFile.close();//
QDate::currentDate().toString(yyyyMMdd);QString
QString(%1/log_%2.txt).arg(logDir).arg(file_day);logFile.setFileName(file_path);if
QTime::currentTime().toString(hhmmss);file_path
QString(%1/log_%2_%3.txt).arg(logDir).arg(file_day).arg(file_time);logFile.setFileName(file_path);}//
(!logFile.open(QIODevice::WriteOnly
原文链接https://blog.csdn.net/u011218356/article/details/103344231
这几天在交接工作把之前手头的一个项目交接一下想着增加一个日志模块去查了一下Qt自带的日志模块
qInstallMessageHandler(QtMessageHandler
打印消息的控制能控制打印的输出调试信息警告严重致命错误等五个等级。
context.function);abort();}}int
**argv){qInstallMessageHandler(myMessageOutput);QApplication
1.读取日志配置文件设置文件输出等级。
可以用做在正式项目中调试与日常关键信息打印。
(!file.open(QIODevice::ReadOnly
QIODevice::Text)){//判断文件是否可执行return;}while
strBuf.mid(strBuf.size()-1,1).toInt();}}
mutex;mutex.lock();//读写消息QByteArray
msg.toLocal8Bit();//输出的字符串QString
\n).arg(QDateTime::currentDateTime().toString(yyyy-MM-dd
hh:mm:ss)).arg(QString(context.file)).arg(context.line).arg(QString(context.function)).arg(QString(localMsg));}break;case
\n).arg(QDateTime::currentDateTime().toString(yyyy-MM-dd
hh:mm:ss)).arg(QString(context.file)).arg(context.line).arg(QString(context.function)).arg(QString(localMsg));}break;case
\n).arg(QDateTime::currentDateTime().toString(yyyy-MM-dd
hh:mm:ss)).arg(QString(context.file)).arg(context.line).arg(QString(context.function)).arg(QString(localMsg));}break;case
\n).arg(QDateTime::currentDateTime().toString(yyyy-MM-dd
hh:mm:ss)).arg(QString(context.file)).arg(context.line).arg(QString(context.function)).arg(QString(localMsg));}break;case
\n).arg(QDateTime::currentDateTime().toString(yyyy-MM-dd
hh:mm:ss)).arg(QString(context.file)).arg(context.line).arg(QString(context.function)).arg(QString(localMsg));}abort();}//每天生成一个新的log日志文件文件名
QString(%1.txt).arg(QDateTime::currentDateTime().date().toString(yyyyMMdd));QFile
logfile(strFileName);logfile.open(QIODevice::WriteOnly
QIODevice::Append);if(strOutStream
logStream(logfile);logStreamstrOutStream\r\n;}//清楚缓存文件解锁logfile.flush();logfile.close();mutex.unlock();
{ReadLogInit();//读取日志等级qInstallMessageHandler(message_output);//安装消息处理函数依靠回调函数重定向全局处理QApplication
argv);qInfo()\r\n\r\n\r\n**PCCamera
原文链接https://blog.csdn.net/yang1fei2/article/details/125210633
在开发QT程序的时候很多开发者也就仅仅用QT的日志模块qDebug一下调试信息在真正的日志记录上还是采用一些别的日志库。
其实QT的日志模块还是很强大的可以满足日常的基本需求。
这里就详细介绍一下QT日志模块的个性化使用方法。
默认情况下日志格式是只输出对应的日志内容没有额外信息的。
我们可以通过修改环境变量QT_MESSAGE_PATTERN或者调用方法
qSetMessagePattern来修改日志的输出格式。
日志格式中常用的占位符号如下所示:
应用程序的名称(QCoreApplication::applicationName())
打印日志的程序的PID(QCoreApplication::applicationPid())
[format]}以固定时间格式输出日志打印的时间默认为QISODate格式格式化日志的调用方法如下:
argv);qSetMessagePattern(%{time
hh:mm:ss}--[%{type}]--%{function}:%{message});qDebug()
10:09:54--[debug]--main:exception
%{if-fatal}给不同级别的日志指定不同的格式使用方法如下:
argv);//针对Warning信息和Fatal信息输出了额外的内容qputenv(QT_MESSAGE_PATTERN,
[%{type}]%{if-warning}[%{function}]%{endif}%{if-fatal}[%{function}--%{line}]%{endif}:%{message}));qDebug()
error我们可以通过修改QT_MESSAGE_PATTERN环境变量动态的修改日志的输出格式。
如果同时调用qSetMessagePattern和QT_MESSAGE_PATTERN环境变量来修改日志的输出格式那么QT_MESSAGE_PATTERN的优先级要高于qSetMessagePattern。
QT默认的日志内容是输出到终端的不会输出到文件里面如果需要将日志内容输出到文件中我们需要通过qInstallMessageHandler设置日志信息处理函数。
使用方法如下:
qFormatLogMessage(type,context,message);//可以根据日志的级别进行过滤QString
file(myapp.log);file.open(QIODevice::WriteOnly
argv);qSetMessagePattern(%{time
[%{type}]%{if-warning}[%{function}]%{endif}%{if-fatal}[%{function}--%{line}]%{endif}:%{message});qInstallMessageHandler(logmessageHander);qDebug()
qInstallMessageHandler(0);日志输出对象信息
在调试一些复杂对象的时候我们需要输出对象的成员信息到日志当中。
但是默认情况下qt的日志库是不支持输出自定义对象的。
这时候我们可以通过重写操作符实现对自定义象的日志输出。
使用方法如下:
}QDebugStateSaver类可以保存QDebug的配置并在销毁的时候自动恢复。
使用它我们可以避免在操作符重载的时候破坏QDebug中的配置。
https://blog.csdn.net/qq_45662588/article/details/116259372
原文链接https://blog.csdn.net/lm409/article/details/74908484
项目中需求一日志模块主要实现两大功能1.自动打印信息至日志文件2.软件意外退出时保留信息以便跟踪问题。
提供的方法补充实现了文章中未具体给出的管理日志文件大小和数量的功能。
环境vs2012Qt5.2(注Qt5.5之后引入qInfo()影响不大)
qInstallMessageHandler()接管qDebug(),
qWarning()等调试信息然后将信息流存储至本地日志文件管理日志文件。
1.更改日志存储名称格式用QDateTime取代QDate以避免当日记录多条日志时的覆盖问题
4.屏蔽根据修改日期保存日志机制以免在不同日期开启软件后冲掉以前的有用log仅凭文件大小另存log文件然后控制文件数量。
/*************************************************************************************************************
************************************************************************************************************/
{LogHandlerPrivate();~LogHandlerPrivate();//
protocal.log如果日志文件不是当天创建的则使用创建日期把其重命名为
QTextStream使用静态对象就是为了减少函数调用的开销static
NULL;LogHandlerPrivate::LogHandlerPrivate()
logDir.absoluteFilePath(protocal.log);
所以不能运行时使用这个函数检查创建时间因为会在运行时变化所以在程序启动时保存下日志文件创建的时间logFileCreatedDate
QFileInfo(logPath).lastModified();//QString
logFileCreatedDate.toString(yyyy-MM-dd
打开日志文件如果不是当天创建的备份已有日志文件openAndBackupLogFile();//
五分钟检查一次日志文件创建时间renameLogFileTimer.setInterval(1000
可从配置文件读取//renameLogFileTimer.setInterval(1000*60);
分钟检查一次renameLogFileTimer.start();QObject::connect(renameLogFileTimer,
locker(LogHandlerPrivate::logMutex);openAndBackupLogFile();});//
定时刷新日志输出到文件尽快的能在日志文件里看到最新的日志flushLogFileTimer.setInterval(1000);
可从配置文件读取flushLogFileTimer.start();QObject::connect(flushLogFileTimer,
QDateTime::currentDateTime().toString(yyyy-MM-dd
locker(LogHandlerPrivate::logMutex);
}checkLogFiles();//每秒检查一次文件是否超过限制大小});
}LogHandlerPrivate::~LogHandlerPrivate()
{logFile-flush();logFile-close();delete
protocal.log如果不是当天创建的则使用创建日期把其重命名为
LogHandlerPrivate::openAndBackupLogFile()
的创建日期和当前日期不相等则使用它的创建日期重命名然后再生成一个新的
logDir.absoluteFilePath(protocal.log);
(logFile-open(QIODevice::WriteOnly
QDateTime::currentDateTime();}}//
程序运行时如果创建日期不是当前日期则使用创建日期重命名并生成一个新的
protocal.log//不使用该特性以免在不同日期开启软件后冲掉以前的有用log仅凭文件大小另存log文件见checkLogFiles
logDir.absoluteFilePath(logFileCreatedDate.toString(yyyy-MM-dd_hhmmss.log));;
(logFile-open(QIODevice::WriteOnly
个删除最早的logDir.setFilter(QDir::Files);logDir.setNameFilters(QStringList()
*.log);//根据文件后缀过滤日志文件QFileInfoList
i)QFile::remove(logFiles[i].absoluteFilePath());//根据文件名称进一步过滤//
logFiles[i].absoluteFilePath());//
QFile::remove(fileDateNames[i]);
LogHandlerPrivate::makeSureLogDirectory()
LogHandlerPrivate::checkLogFiles()
文件大小超过5M重新创建一个日志文件原文件存档为yyyy-MM-dd_hhmmss.logif
{logFile-flush();logFile-close();delete
logDir.absoluteFilePath(protocal.log);
logDir.absoluteFilePath(logFileCreatedDate.toString(yyyy-MM-dd_hhmmss.log));;QFile::copy(logPath,
(logFile-open(QIODevice::WriteOnly
QDateTime::currentDateTime();if
LogHandlerPrivate::messageHandler(QtMsgType
locker(LogHandlerPrivate::logMutex);QString
fileName.lastIndexOf(QDir::separator());fileName
1);(*LogHandlerPrivate::logOut)
%5\n).arg(QDateTime::currentDateTime().toString(yyyy-MM-dd
hh:mm:ss)).arg(level).arg(fileName).arg(context.line)/*.arg(context.function)*/.arg(msg);logOut-flush();//直接刷新到文件
}/*************************************************************************************************************
************************************************************************************************************/
LogHandler::installMessageHandler()
locker(LogHandlerPrivate::logMutex);if
LogHandlerPrivate();qInstallMessageHandler(LogHandlerPrivate::messageHandler);
locker(LogHandlerPrivate::logMutex);qInstallMessageHandler(0);delete
让程序在崩溃时体面的退出之总结博主在系列文章中做了详尽的说明。
我的应用目的是在程序崩溃时能体面退出然后记录基本的CallStack信息到日志文件所以只用到了前面两部分内容。
在上文的基础上用qCritical()或其他方法输出Crash信息和CallStack信息即可。
ApplicationCrashHandler(EXCEPTION_POINTERS
*pException){/****保存数据代码****///
DumpDir.absoluteFilePath(ProtocolTester.dmp).utf16();//
Dump文件的路径CreateDumpFile(DumpPath,
(pException-ExceptionRecord-ExceptionCode
GetCrashInfo(pException-ExceptionRecord);
GetCallStack(pException-ContextRecord);
}//这里弹出一个错误对话框并退出程序EXCEPTION_RECORD*
pException-ExceptionRecord;QString
errCode(QString::number(record-ExceptionCode,16)),errAdr(QString::number((uint)record-ExceptionAddress,16)),errMod;QMessageBox::critical(NULL,QStringLiteral(Error),QStringLiteral(FONT
size4divb很抱歉程序出错了。
/bbr//div)QStringLiteral(div错误代码%1/divdiv错误地址%2/div/FONT).arg(errCode).arg(errAdr),QMessageBox::Ok);return
本文实现了一个轻量的Qt日志模块功能肯定是没有log4qt或log4cxx等强大但也基本满足了项目应用需求想了解log4qt也可以查看DevBean豆子大神的github
原文链接https://blog.csdn.net/feiyangqingyun/article/details/121314920
之前已经开源过基础版本近期根据客户需求和自己的项目需求提炼出通用需求部分对整个日志重定向输出类重新规划和重写代码。
用Qt这个一站式超大型GUI超市做开发已经十二年了陆陆续续开发过至少几十个程序除了一些算不算项目的小工具外大部分的程序都需要有个日志的输出功能希望可以将程序的运行状态存储到文本文件或者数据库或者做其他处理等Qt对这个日志输出也做了很好的封装在Qt4是qInstallMsgHandlerQt5及Qt6里边是qInstallMessageHandler有了这个神器只要在你的项目中所有qDebug
网上大部分人写的demo都是接收到输出打印日志存储到文本文件其实这就带给很多人误解容易产生以为日志只能输出到文本文件其实安装了日志钩子以后拿到了所有调试打印信息你完全可以用来存储到数据库及输出html有颜色区分格式的文件或者网络转发输出尤其适用于嵌入式linux无界面程序现场不方便外接调试打印的设备。
做过的这么多项目中Qt4、Qt5、Qt6的都有我一般保留四个版本4.8.7为了兼容Qt4,
最高的新版本6.2.1。
毫无疑问我要封装的这个日志类也要同时支持Qt4、Qt5、Qt6的而且提供友好的接口。
使用方式最简单调用函数start()启动服务stop()停止服务。
以上作品完整源码下载都在开源主页会持续不断更新作品数量和质量欢迎各位关注。
本开源项目已经成功升级到V2.0版本分门别类图文并茂保你爽到爆。
国内站点https://gitee.com/feiyangqingyun/QWidgetDemo
国际站点https://github.com/feiyangqingyun/QWidgetDemo
开源秘籍https://gitee.com/feiyangqingyun/qtkaifajingyan
个人主页https://qtchina.blog.csdn.net/
视频主页https://space.bilibili.com/687803542
execution_character_set(utf-8)#include
qPrintable(QDate::currentDate().toString(yyyy-MM-dd))
qPrintable(QDateTime::currentDateTime().toString(yyyy-MM-dd-HH-mm-ss))//日志重定向
{//加锁,防止多线程中qdebug太频繁导致崩溃static
content;//这里可以根据不同的类型加上不同的头部用于区分int
SaveLog::Instance()-getMsgType();switch
%1).arg(msg);}break;}//没有内容则返回if
(SaveLog::Instance()-getUseContext())
%3\n%4).arg(line).arg(file).arg(function).arg(content);}}
#endif//还可以将数据转成html内容分颜色区分//将内容传给函数进行处理SaveLog::Instance()-save(content);
thread//估计日志钩子可能单独开了线程connect(this,
true;//全局的文件对象,在需要的时候打开而不是每次添加日志都打开file
qApp-applicationDirPath();//默认取应用程序可执行文件名称QString
qApp-applicationFilePath();QStringList
{//当文件名改变时才新建和打开文件而不是每次都打开文件(效率极低)或者一开始打开文件if
{file-close();}//重新设置新的日志文件file-setFileName(fileName);//以
追加的形式打开file-open(QIODevice::WriteOnly
QT_VERSION_CHECK(5,0,0))qInstallMessageHandler(Log);
QT_VERSION_CHECK(5,0,0))qInstallMessageHandler(0);
{//如果重定向输出到网络则通过网络发出去,否则输出到日志文件if
{dir.mkdir(path);}//日志存储规则有多种策略
都没有设置都存储到日期命名的文件,只有当日期变化了才会切换到新的日志文件bool
方法速度非常快//首次需要重新打开文件以及超过大小需要重新打开文件if
QString(%1/%2_log_%3.txt).arg(path).arg(name).arg(QDATE);openFile(fileName);}if
QString(%1/%2_log_%3.txt).arg(path).arg(name).arg(QDATETIMS);openFile(fileName);}//用文本流的输出速度更快QTextStream
{SendLog::Instance()-setListenPort(listenPort);
QTcpServer(this);connect(server,
{socket-disconnectFromHost();}server-close();
(server-hasPendingConnections())
server-nextPendingConnection();}
QT_VERSION_CHECK(5,0,0))server-listen(QHostAddress::AnyIPv4,
#elseserver-listen(QHostAddress::Any,
{socket-disconnectFromHost();socket
{socket-write(content.toUtf8());//socket-flush();}
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback