您的位置:首页 > 编程语言 > Qt开发

Qt5的Log打印

2016-03-17 22:33 525 查看
背景:

一般情况下,我们调试版本会在code里面添加一些qDebug来帮助我们修改代码。

但是当我们的软件版本发布出去,用户告诉我们软件使用出问题了,并且我们在自己的实验室无法复现问题怎么办?

这个时候怎么依靠我们之前在代码里面添加的qDebug呢?

只要用户动动小手,改个配置文件就会把原来代码里面的log输出到一个txt里,然后送给我们分析问题。

方法:

首先,我们使用帮助文档看下Qt5的这个方法

QtMessageHandler qInstallMessageHandler(QtMessageHandler handler)
我们可以看到下面信息。

#include <qapplication.h>
#include <stdio.h>
#include <stdlib.h>

void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QByteArray localMsg = msg.toLocal8Bit();
switch (type) {
case QtDebugMsg:
fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtInfoMsg:
fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtWarningMsg:
fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtCriticalMsg:
fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtFatalMsg:
fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
abort();
}
}

int main(int argc, char **argv)
{
qInstallMessageHandler(myMessageOutput);
QApplication app(argc, argv);
...
return app.exec();
}


显而易见,它给我们举了个例子,告诉我们怎么使用,并且也详细描述了。

The message handler is a function that prints out debug messages, warnings, critical and fatal error messages. The Qt library (debug mode) contains hundreds of warning messages that
are printed when internal errors (usually invalid function arguments) occur. Qt built in release mode also contains such warnings unless QT_NO_WARNING_OUTPUT and/or QT_NO_DEBUG_OUTPUT have been set during compilation. If you implement your own message handler,
you get total control of these messages.

我们只需要把他的信息保留到txt文件中就可以了。

同时在代码里面定义个宏,
#ifndef QT_DEBUG
installReleaseMsgHandler();
#endif
Debug模式在QtCreater里面显示,Release模式编译输出文件流。

注意:

如果Release模式下,在软件运行输出日志到txt的时候,用户这时关闭软件,我们必须要有个关闭txt文件的操作。

这个时候你需要了解下 这个函数

void qAddPostRoutine(QtCleanUpFunction ptr)
Adds a global routine that will be called from the QCoreApplication destructor. This function is normally
used to add cleanup routines for program-wide functionality.

以上基本就可以满足我们的要求了。

下来请赏脸看下我写的例子:

#include <QApplication>
#include <stdio.h>
#include <stdlib.h>
#include <QCoreApplication>
#include <QSettings>
#include <QDebug>
#include <QTime>
#include <QDir>

#define _TIME_ qPrintable(QTime::currentTime().toString("hh:mm:ss:zzz"))

static FILE *q_fileStream = NULL;
static int   g_logLevel   = 0;

enum TraceLevel
{
TL_NULL = 0,
TL_CRIT,
TL_ERRO,
TL_WARN,
TL_INFO
};

static const int g_TraceLevel [] = { TL_INFO, TL_WARN, TL_ERRO, TL_CRIT, TL_NULL };

static void SoftWareShutDown ()
{
if (NULL != q_fileStream)
{
qDebug("Close log file.");
fclose (q_fileStream);
q_fileStream = NULL;
}
}

void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
Q_UNUSED(type);
QByteArray localMsg = msg.toLocal8Bit();
if (g_logLevel && q_fileStream)
{
int iLevel = g_TraceLevel[type];
if (g_logLevel < iLevel)
{
return;
}

fprintf (q_fileStream, "%s: %s (%s:%u, %s)\n", _TIME_, localMsg.constData(), context.file, context.line, context.function);
fflush (q_fileStream);
}
}

static void installMsgHandler(QString strLogFile)
{
QByteArray byteArrayLogFile = strLogFile.toLatin1();

if (NULL != q_fileStream)
{
fclose (q_fileStream);
q_fileStream = NULL;
}

q_fileStream = fopen (byteArrayLogFile.constData (), "w+");
if (NULL != q_fileStream)
{
qDebug("Opened log file.");
qInstallMessageHandler(myMessageOutput);
}
else
{
qDebug("Failed to open log file.");
}
}

static void installReleaseMsgHandler ()
{
QString strAppPath = QCoreApplication::applicationDirPath();
QString strIniFile = strAppPath + "/RunInfo.ini";
QString strLogFile = strAppPath + "/log.txt";
QSettings pSettings(strIniFile, QSettings::IniFormat);
g_logLevel = pSettings.value("TraceSet/TraceLevel", 1).toInt();
installMsgHandler (strLogFile);
}

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
#ifndef QT_DEBUG
bool bAddQuitFunc = false;
installReleaseMsgHandler();
if (!bAddQuitFunc)
{
qAddPostRoutine (SoftWareShutDown);
bAddQuitFunc = true;
}
#endif
Window w;
w.show();
return a.exec();
}


运行顺序:

1. 判断是否为Release

2. installReleaseMsgHandler // 初始化 ini信息,和log文件位置

3. installMsgHandler // 打开文件,并调用 qInstallMessageHandler

4. myMessageOutput // 根据之前 读取的log等级 按照要求输出log

5. qAddPostRoutine // 检测软件是否关闭,调用关闭文件函数

6. SoftWareShutDown // 关闭文件

同时说明下,我的RunInfo.ini文件信息

就两行

[TraceSet]

TraceLevel=4

平时为1 ,当我们需要打log的时候改为4(全部信息,qDebug/qWarning/qCritical/qInfo),改为3的时候....自己试试吧。

上面代码的CSDN链接:http://download.csdn.net/detail/c3060911030/9464986

主要 ini文件要放置正确位置,在运行目录下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: