Qt5如何輸出日誌輸出檔案(最全最新的框架方法)
Qt5如何輸出日誌輸出檔案目錄
描述
最近用到了Qt5的日誌輸出功能模組,現記錄一下,途中還遇見一些release版本日誌輸出不顯示行號的問題。
迴歸正題:在Qt開發過程當中經常使用qDebug等一些輸出來除錯程式,但是到了正式釋出的時候,都會被註釋或者刪除,採用日誌輸出來代替。
做過專案的童鞋可能都使用過日誌功能,以便有異常錯誤能夠快速跟蹤、定位,Qt也提供的類似的機制。之前用Qt4做專案時使用的是Qt::qInstallMsgHandler(),到了Qt5,使用了新的Qt::qInstallMessageHandler()來替代,詳情請檢視Qt助手(C++ API changes)。
助手中在C++ API changes中提到:Qt::qDebug()、Qt::qWarning()、Qt::qCritical()、Qt::qFatal()被改變為巨集來跟蹤原始碼的訊息來源。被列印的資訊可以被配置(用於預設訊息處理程式),通過設定該新的環境變數QT_MESSAGE_PATTERN。Qt::qInstallMsgHandler()已過時,因此建議使用Qt::qInstallMessageHandler()來代替。
日誌級別
- qDebug:除錯資訊
- qWarning:警告資訊
- qCritical:嚴重錯誤
- qFatal:致命錯誤
官方示例
需求(目的):生成log.txt日誌檔案,記錄詳細日誌資訊(包括等級、所在檔案、所在行號、描述資訊、產生時間等),以便於快速跟蹤、定位。
程式碼實現
#define FILEName "logger.txt"
class MessageHandler: public QObject{
Q_OBJECT
public:
explicit MessageHandler(QObject *parent = nullptr)
{
Q_UNUSED (parent);
//註冊MessageHandler
qInstallMessageHandler(MessageHandler::outputMessage);
}
private:
static void outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
static QMutex mutex;
mutex.lock();
QString text;
switch(type)
{
case QtDebugMsg:
text = QString("Debug:");
break;
case QtWarningMsg:
text = QString("Warning:");
break;
case QtCriticalMsg:
text = QString("Critical:");
break;
case QtFatalMsg:
text = QString("Fatal:");
break;
case QtInfoMsg:
text = QString("Info:");
break;
}
QString context_info = QString("File:(%1) Line:(%2)").arg(QString(context.file)).arg(context.line);
QString current_date_time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");
QString current_date = QString("(%1)").arg(current_date_time);
QString message = QString("%1 %2 %3 %4").arg(text).arg(context_info).arg(msg).arg(current_date);
QString logPath ;
#if defined (Q_OS_ANDROID)
QStringList stringList = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
// qInfo()<<"當前獲取到的stringList = "<<stringList;
logPath = stringList.at(stringList.length() - 1);
int indexPosition = logPath.lastIndexOf("/");
if(indexPosition != -1)
{
logPath = logPath.mid(0, indexPosition);
if(!isDirExist(logPath+"/YYM"))
{
qInfo("Failed to create log directory.");
}
else
{
logPath = logPath+"/YYM";
}
}
#else
logPath = HelpClass::getCurrentTempDataDir()+"/Logger";
HelpClass::isDirExist(logPath);
// qInfo()<<"當前獲取到的stringList = "<<logPath;
#endif
QString date = QDateTime::currentDateTime().toString("yyyy-MM-dd");
logPath = logPath +QString("/logger(%1).txt").arg(date);
// qInfo()<<"LogPath = "<<logPath;
QFile file(logPath);
file.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream text_stream(&file);
text_stream.setCodec("UTF-8");
text_stream << message << "\r\n";
file.flush();
file.close();
mutex.unlock();
}
};
#endif // MESSAGEHANDLER_H
使用方法:
在main裡面呼叫即可
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MessageHandler *message = new MessageHandler;
//列印日誌到檔案中
qDebug("This is a debug message");
qWarning("This is a warning message");
qCritical("This is a critical message");
qFatal("This is a fatal message");
return a.exec();
}
注意!注意!注意!(重要的事情說三遍)
Release版本的輸出卻沒有檔案資訊、行數等資訊,如圖。
Release輸出
原因是:檔案資訊、行數等資訊在Release版本預設捨棄。我們只要在.pro檔案定義一個巨集
DEFINES += QT_MESSAGELOGCONTEXT
DEFINES += QT_MESSAGELOGCONTEXT
然後,重新qmake,編譯(有可能要刪除掉之前編譯的中間檔案),就可以在Release版本中正確輸出日誌資訊,如圖。