Qt5的Log打印

背景:

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

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

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

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

方法:

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

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

  1. #include <qapplication.h>  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4.   
  5. void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)  
  6. {  
  7.     QByteArray localMsg = msg.toLocal8Bit();  
  8.     switch (type) {  
  9.     case QtDebugMsg:  
  10.         fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);  
  11.         break;  
  12.     case QtInfoMsg:  
  13.         fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);  
  14.         break;  
  15.     case QtWarningMsg:  
  16.         fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);  
  17.         break;  
  18.     case QtCriticalMsg:  
  19.         fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);  
  20.         break;  
  21.     case QtFatalMsg:  
  22.         fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);  
  23.         abort();  
  24.     }  
  25. }  
  26.   
  27. int main(int argc, char **argv)  
  28. {  
  29.     qInstallMessageHandler(myMessageOutput);  
  30.     QApplication app(argc, argv);  
  31.     ...  
  32.     return app.exec();  
  33. }  

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

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文件中就可以了。

同时在代码里面定义个宏,

  1. #ifndef QT_DEBUG  
  2.     installReleaseMsgHandler();  
  3. #endif  
Debug模式在QtCreater里面显示,Release模式编译输出文件流。

注意:

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

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

  1. 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.

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

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

  1. #include <QApplication>  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <QCoreApplication>  
  5. #include <QSettings>  
  6. #include <QDebug>  
  7. #include <QTime>  
  8. #include <QDir>  
  9.   
  10. #define _TIME_ qPrintable(QTime::currentTime().toString("hh:mm:ss:zzz"))  
  11.   
  12. static FILE *q_fileStream = NULL;  
  13. static int   g_logLevel   = 0;  
  14.   
  15. enum TraceLevel  
  16. {  
  17.     TL_NULL = 0,  
  18.     TL_CRIT,  
  19.     TL_ERRO,  
  20.     TL_WARN,  
  21.     TL_INFO  
  22. };  
  23.   
  24. static const int g_TraceLevel [] = { TL_INFO, TL_WARN, TL_ERRO, TL_CRIT, TL_NULL };  
  25.   
  26. static void SoftWareShutDown ()  
  27. {  
  28.     if (NULL != q_fileStream)  
  29.     {  
  30.         qDebug("Close log file.");  
  31.         fclose (q_fileStream);  
  32.         q_fileStream = NULL;  
  33.     }  
  34. }  
  35.   
  36. void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)  
  37. {  
  38.     Q_UNUSED(type);  
  39.     QByteArray localMsg = msg.toLocal8Bit();  
  40.     if (g_logLevel && q_fileStream)  
  41.     {  
  42.         int iLevel = g_TraceLevel[type];  
  43.         if (g_logLevel < iLevel)  
  44.         {  
  45.             return;  
  46.         }  
  47.   
  48.         fprintf (q_fileStream, "%s: %s (%s:%u, %s)\n", _TIME_, localMsg.constData(), context.file, context.line, context.function);  
  49.         fflush (q_fileStream);  
  50.     }  
  51. }  
  52.   
  53. static void installMsgHandler(QString strLogFile)  
  54. {  
  55.     QByteArray byteArrayLogFile = strLogFile.toLatin1();  
  56.   
  57.     if (NULL != q_fileStream)  
  58.     {  
  59.         fclose (q_fileStream);  
  60.         q_fileStream = NULL;  
  61.     }  
  62.   
  63.     q_fileStream = fopen (byteArrayLogFile.constData (), "w+");  
  64.     if (NULL != q_fileStream)  
  65.     {  
  66.         qDebug("Opened log file.");  
  67.         qInstallMessageHandler(myMessageOutput);  
  68.     }  
  69.     else  
  70.     {  
  71.         qDebug("Failed to open log file.");  
  72.     }  
  73. }  
  74.   
  75. static void installReleaseMsgHandler ()  
  76. {  
  77.     QString strAppPath = QCoreApplication::applicationDirPath();  
  78.     QString strIniFile = strAppPath + "/RunInfo.ini";  
  79.     QString strLogFile = strAppPath + "/log.txt";  
  80.     QSettings pSettings(strIniFile, QSettings::IniFormat);  
  81.     g_logLevel = pSettings.value("TraceSet/TraceLevel", 1).toInt();  
  82.     installMsgHandler (strLogFile);  
  83. }  
  84.   
  85. int main(int argc, char *argv[])  
  86. {  
  87.     QApplication a(argc, argv);  
  88. #ifndef QT_DEBUG  
  89.     bool bAddQuitFunc = false;  
  90.     installReleaseMsgHandler();  
  91.     if (!bAddQuitFunc)  
  92.     {  
  93.         qAddPostRoutine (SoftWareShutDown);  
  94.         bAddQuitFunc = true;  
  95.     }  
  96. #endif  
  97.     Window w;  
  98.     w.show();  
  99.     return a.exec();  
  100. }  

运行顺序:

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文件要放置正确位置,在运行目录下。

猜你喜欢

转载自blog.csdn.net/zx249388847/article/details/79961097
Qt5
今日推荐