QLog
1、为什么需要日志?
| 只有在程序出问题以后才会知道打一个好的日志有多么重要 |
- 当程序出现问题了,然后不是稳定复现的问题。怎么办法?
- 当前程序出现问题了,当前环境不支持调试。例如:例如线上远程环境。
- 当程序出现问题了,你不知道用户进行了哪些意想不到的奇葩操作
- 在程序开发时输出日志是一个非常好的习惯,在qt中输出日志信息很多人都是使用一个QTextEdit显示就完了,或者加上点击按键保存到txt里,这种方式使得日志模块与程序耦合度非常高,使用也非常不方便,保存的日志信息也不完整,这就导致想通过日志获取需要的信息时常常找不到有效信息;
- 这就需要在程序中使用一个低耦合,使用方便、日志信息完整的日志系统,qt可以使用很多C++的日志库,但是引入第三方库也比较麻烦;
- 这里就可以直接将QDebug的日志信息输出到日志文件中,无需引入第三方库,使用也非常简单。
2、实现方式
- 通过
qInstallMessageHandler安装日志处理函数,获取QDebug的日志信息,然后保存、显示。
3、实现功能
- 可选择日志显示到文本窗口并保存、不显示只保存两种使用方式;
- 选择显示日志级别;
- 可设置不同级别日志显示颜色;
- 支持将日志信息保存到纯文本Log文件中;
- 支持将日志信息保存到纯文本CSV文件中,便于阅读、查找和分类日志信息,可用于将CSV中的日志信息导入数据库;
- 支持按12小时、24小时、按文件大小、日志行数创建新日志文件;
- 无任何第三方依赖,支持任意编译器,任意系统;
- 保留日志存储接口、日志显示接口,便于后续扩展日志存储、显示方式,如存储到数据库等;
- 模块完全基于QDebug,与程序所有功能基本0耦合,非常便于程序开发。
- 输出日志信息包含时间、日志级别、日志出自哪个文件、哪个函数、哪一行、日志内容。
4、演示



5、主要代码
#include "loginput.h"
#include "head.h"
QtMessageHandler messageHandle;
LogInput::LogInput(QObject *parent) : QObject(parent)
{
LogConfig::init();
qRegisterMetaType<QtMsgType>("QtMsgType");
messageHandle = qInstallMessageHandler(LogInput::myMessageOutput);
}
LogInput::~LogInput()
{
qInstallMessageHandler(0);
}
LogInput* LogInput::m_log = nullptr;
LogInput *LogInput::getInstance()
{
if(nullptr == m_log)
{
static QMutex mutex;
QMutexLocker locker(&mutex);
if(nullptr == m_log)
{
m_log = new LogInput();
}
}
return m_log;
}
void LogInput::myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QByteArray localMsg = msg.toLocal8Bit();
switch (type) {
case QtDebugMsg:
break;
case QtInfoMsg:
break;
case QtWarningMsg:
break;
case QtCriticalMsg:
break;
case QtFatalMsg:
break;
}
if(!msg.isEmpty())
{
const char *file = context.file ? context.file : "";
const char *function = context.function ? context.function : "";
emit m_log->logData(type, QTime::currentTime(), file, function, context.line, msg);
}
messageHandle(type, context, msg);
}
6、源代码
gitee
github
7、崩溃定位