Ниже приведен код класса, который можно использовать в качестве подсистемы логирования в приложении на Qt. Данный класс перехватывает все отладочные сообщения, генерируемые через qDebug(), qWarning() и прочие функции потокового отладочного вывода, печатает их в консоль и записывает в файл лога.
Заголовок
#ifndef LOGHELPER_H
#define LOGHELPER_H
#include <QDebug>
class LogHelper
{
public:
static void setDebugMessageHandler();
static void myMessageOutput(QtMsgType type,
const QMessageLogContext &context,
const QString &msgText);
protected:
static void smartPrintDebugMessage(QString msg);
static void printToLogFile(const QString &text);
static void clearLogFile();
static QString m_logFileName;
};
#endif // LOGHELPER_H
Реализация
#include <QDebug>
#include <QObject>
#include <QApplication>
#include <QString>
#include <QTime>
#include <QMessageBox>
#include <iostream>
#include "log_helper.h"
QString LogHelper::m_logFileName;
void LogHelper::clearLogFile()
{
// Создание пустого файла лога
FILE *pFile=fopen(qPrintable(m_logFileName), "w+");
if(!pFile)
{
fclose(pFile);
}
}
void LogHelper::printToLogFile(const QString &text)
{
// Лог-файл открывается в режиме добавления данных
FILE *pFile=fopen(qPrintable(m_logFileName), "a+");
if(!pFile)
{
printf("Log %s file not writable\n", qPrintable(m_logFileName));
return;
}
// Быстрый вывод текста в файл лога
fprintf(pFile, "%s", qPrintable(text));
// Лог-файл закрывается
fclose(pFile);
}
void LogHelper::smartPrintDebugMessage(QString msg)
{
// Подготовка текста для вывода
QTime currTime = QTime::currentTime();
QString timeText = currTime.toString("hh:mm:ss.zzz");
msg=timeText+" "+msg;
// Быстрый вывод в консоль
fprintf(stderr, "%s", qPrintable(msg));
// Вывод в файл лога
printToLogFile(msg);
}
// Обработчик (хендлер) вызовов qDebug()
// Внутри этого обработчика нельзя использовать вызовы qDebug(), т. к. получится рекурсия
void LogHelper::myMessageOutput(QtMsgType type,
const QMessageLogContext &context,
const QString &msgText)
{
Q_UNUSED(context)
switch (type) {
case QtDebugMsg:
// Отладочный вывод возможен только при компиляции в режиме отладки
#ifdef QT_DEBUG
smartPrintDebugMessage("[DBG] "+msgText+"\n");
#endif
break;
case QtWarningMsg:
smartPrintDebugMessage("[WRN] "+msgText+"\n");
QMessageBox::warning(nullptr, "Application warning message",
msgText,
QMessageBox::Ok);
break;
case QtCriticalMsg:
smartPrintDebugMessage("[CRERR] "+msgText+"\n");
QMessageBox::warning(nullptr, "Application critical message",
msgText,
QMessageBox::Ok);
break;
case QtFatalMsg:
smartPrintDebugMessage("[FTERR] "+msgText+"\n");
abort();
case QtInfoMsg:
smartPrintDebugMessage("[INF] "+msgText+"\n");
break;
}
}
void LogHelper::setDebugMessageHandler()
{
// Задается статическое значение имени файла лога
m_logFileName=qApp->applicationDirPath()+"/log.txt";
printf("\nSet log file to %s\n", qPrintable(m_logFileName));
// Лог-файл очищается
clearLogFile();
// Устанавливается Qt-обработчик консольного вывода
qInstallMessageHandler(myMessageOutput);
}
Использование:
#include "log_helper.h"
...
LogHelper::setDebugMessageHandler();
Вызов setDebugMessageHandler() имеет смысл делать как можно ближе к самому началу программы, чтобы все сообщения попадали в файл лога.