Save logs for Tape and Puzzle apps in log file on disk for sending with crash reports.

This commit is contained in:
Roman Telezhynskyi 2024-03-13 15:45:28 +02:00
parent eb4f8719f2
commit 24d39bffb7
5 changed files with 214 additions and 56 deletions

View File

@ -33,12 +33,11 @@
#include "../ifc/exception/vexceptionemptyparameter.h"
#include "../ifc/exception/vexceptionobjecterror.h"
#include "../ifc/exception/vexceptionwrongid.h"
#include "../vganalytics/def.h"
#include "../vganalytics/vganalytics.h"
#include "../vmisc/projectversion.h"
#include "../vmisc/qt_dispatch/qt_dispatch.h"
#include "../vmisc/theme/vtheme.h"
#include "../vmisc/vsysexits.h"
#include "version.h"
#include "vpmainwindow.h"
#include "vpuzzleshortcutmanager.h"
@ -159,29 +158,55 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con
type = QtDebugMsg;
}
switch (type)
{
case QtDebugMsg:
vStdOut() << QApplication::translate("mNoisyHandler", "DEBUG:") << msg << "\n";
return;
case QtWarningMsg:
vStdErr() << QApplication::translate("mNoisyHandler", "WARNING:") << msg << "\n";
break;
case QtCriticalMsg:
vStdErr() << QApplication::translate("mNoisyHandler", "CRITICAL:") << msg << "\n";
break;
case QtFatalMsg:
vStdErr() << QApplication::translate("mNoisyHandler", "FATAL:") << msg << "\n";
break;
case QtInfoMsg:
vStdOut() << QApplication::translate("mNoisyHandler", "INFO:") << msg << "\n";
break;
default:
break;
}
QString debugdate = "["_L1 + QDateTime::currentDateTime().toString(QStringLiteral("yyyy.MM.dd hh:mm:ss"));
vStdOut().flush();
vStdErr().flush();
switch (type)
{
case QtDebugMsg:
debugdate += QStringLiteral(":DEBUG:%1(%2)] %3: %4: %5")
.arg(context.file)
.arg(context.line)
.arg(context.function, context.category, msg);
vStdOut() << QApplication::translate("mNoisyHandler", "DEBUG:") << msg << "\n";
break;
case QtWarningMsg:
debugdate += QStringLiteral(":WARNING:%1(%2)] %3: %4: %5")
.arg(context.file)
.arg(context.line)
.arg(context.function, context.category, msg);
vStdErr() << QApplication::translate("mNoisyHandler", "WARNING:") << msg << "\n";
break;
case QtCriticalMsg:
debugdate += QStringLiteral(":CRITICAL:%1(%2)] %3: %4: %5")
.arg(context.file)
.arg(context.line)
.arg(context.function, context.category, msg);
vStdErr() << QApplication::translate("mNoisyHandler", "CRITICAL:") << msg << "\n";
break;
case QtFatalMsg:
debugdate += QStringLiteral(":FATAL:%1(%2)] %3: %4: %5")
.arg(context.file)
.arg(context.line)
.arg(context.function, context.category, msg);
vStdErr() << QApplication::translate("mNoisyHandler", "FATAL:") << msg << "\n";
break;
case QtInfoMsg:
debugdate += QStringLiteral(":INFO:%1(%2)] %3: %4: %5")
.arg(context.file)
.arg(context.line)
.arg(context.function, context.category, msg);
vStdOut() << QApplication::translate("mNoisyHandler", "INFO:") << msg << "\n";
break;
default:
break;
}
vStdOut().flush();
vStdErr().flush();
(*VPApplication::VApp()->LogFile()) << debugdate << Qt::endl;
}
if (isGuiThread)
{
@ -209,8 +234,6 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con
messageBox.setIcon(QMessageBox::Information);
break;
case QtDebugMsg:
Q_UNREACHABLE(); //-V501
break;
default:
break;
}
@ -405,10 +428,10 @@ auto VPApplication::NewMainWindow(const VPCommandLinePtr &cmd) -> VPMainWindow *
//---------------------------------------------------------------------------------------------------------------------
void VPApplication::InitOptions()
{
qInstallMessageHandler(noisyFailureMsgHandler);
OpenSettings();
StartLogging();
qCDebug(pApp, "Version: %s", qUtf8Printable(AppVersionStr()));
qCDebug(pApp, "Build revision: %s", BUILD_REVISION);
qCDebug(pApp, "%s", qUtf8Printable(buildCompatibilityString()));
@ -443,6 +466,22 @@ void VPApplication::InitOptions()
m_shortcutManager = new VPuzzleShortcutManager(this);
}
//---------------------------------------------------------------------------------------------------------------------
void VPApplication::StartLogging()
{
if (CreateLogDir())
{
BeginLogging();
ClearOldLogs();
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VPApplication::LogFile() -> QTextStream *
{
return m_out.get();
}
//---------------------------------------------------------------------------------------------------------------------
auto VPApplication::TrVars() -> const VTranslateVars *
{
@ -723,6 +762,38 @@ auto VPApplication::SingleStart(const VPCommandLinePtr &cmd, const QStringList &
return true;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPApplication::LogPath() -> QString
{
// Keep in sync with VCrashPaths::GetAttachmentPath
return QStringLiteral("%1/puzzle-pid%2.log").arg(LogDirPath()).arg(applicationPid());
}
//---------------------------------------------------------------------------------------------------------------------
void VPApplication::BeginLogging()
{
VlpCreateLock(m_lockLog, LogPath(), []() { return new QFile(LogPath()); });
if (m_lockLog->IsLocked())
{
if (m_lockLog->GetProtected()->open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
{
m_out.reset(new QTextStream(m_lockLog->GetProtected().data()));
qInstallMessageHandler(noisyFailureMsgHandler);
qCDebug(pApp, "Log file %s was locked.", qUtf8Printable(LogPath()));
}
else
{
qCDebug(pApp, "Error opening log file \'%s\'. All debug output redirected to console.",
qUtf8Printable(LogPath()));
}
}
else
{
qCDebug(pApp, "Failed to lock %s", qUtf8Printable(LogPath()));
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VPApplication::CommandLine() -> VPCommandLinePtr
{

View File

@ -30,6 +30,7 @@
#include "../vmisc/def.h"
#include "../vmisc/vabstractapplication.h"
#include "../vmisc/vlockguard.h"
#include "vpcommandline.h"
#include "vpsettings.h"
@ -62,6 +63,9 @@ public:
void InitOptions();
void StartLogging();
auto LogFile() -> QTextStream *;
auto TrVars() -> const VTranslateVars * override;
void OpenSettings() override;
@ -95,6 +99,8 @@ private:
QList<QPointer<VPMainWindow>> m_mainWindows{};
QLocalServer *m_localServer{nullptr};
QWeakPointer<DialogPuzzlePreferences> m_preferencesDialog{};
QSharedPointer<VLockGuard<QFile>> m_lockLog{};
std::shared_ptr<QTextStream> m_out{nullptr};
void Clean();
@ -102,6 +108,9 @@ private:
auto StartWithFiles(const VPCommandLinePtr &cmd, const QStringList &rawLayouts) -> bool;
auto SingleStart(const VPCommandLinePtr &cmd, const QStringList &rawLayouts) -> bool;
static auto LogPath() -> QString;
void BeginLogging();
};
#endif // VPAPPLICATION_H

View File

@ -35,7 +35,6 @@
#include "../ifc/exception/vexceptionwrongid.h"
#include "../qmuparser/qmuparsererror.h"
#include "../vformat/knownmeasurements/vknownmeasurementsdatabase.h"
#include "../vganalytics/def.h"
#include "../vganalytics/vganalytics.h"
#include "../vmisc/projectversion.h"
#include "../vmisc/qt_dispatch/qt_dispatch.h"
@ -66,7 +65,6 @@
#include <QThread>
#include <QTranslator>
#include <QUuid>
#include <iostream>
#if !defined(BUILD_REVISION) && defined(QBS_BUILD)
#include <QEvent>
@ -197,29 +195,55 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con
logMsg = logMsg.remove(VAbstractApplication::warningMessageSignature);
}
switch (type)
{
case QtDebugMsg:
vStdOut() << QApplication::translate("mNoisyHandler", "DEBUG:") << logMsg << "\n";
return;
case QtWarningMsg:
vStdErr() << QApplication::translate("mNoisyHandler", "WARNING:") << logMsg << "\n";
break;
case QtCriticalMsg:
vStdErr() << QApplication::translate("mNoisyHandler", "CRITICAL:") << logMsg << "\n";
break;
case QtFatalMsg:
vStdErr() << QApplication::translate("mNoisyHandler", "FATAL:") << logMsg << "\n";
break;
case QtInfoMsg:
vStdOut() << QApplication::translate("mNoisyHandler", "INFO:") << logMsg << "\n";
break;
default:
break;
}
QString debugdate = "["_L1 + QDateTime::currentDateTime().toString(QStringLiteral("yyyy.MM.dd hh:mm:ss"));
vStdOut().flush();
vStdErr().flush();
switch (type)
{
case QtDebugMsg:
debugdate += QStringLiteral(":DEBUG:%1(%2)] %3: %4: %5")
.arg(context.file)
.arg(context.line)
.arg(context.function, context.category, logMsg);
vStdOut() << QApplication::translate("mNoisyHandler", "DEBUG:") << logMsg << "\n";
break;
case QtWarningMsg:
debugdate += QStringLiteral(":WARNING:%1(%2)] %3: %4: %5")
.arg(context.file)
.arg(context.line)
.arg(context.function, context.category, logMsg);
vStdErr() << QApplication::translate("mNoisyHandler", "WARNING:") << logMsg << "\n";
break;
case QtCriticalMsg:
debugdate += QStringLiteral(":CRITICAL:%1(%2)] %3: %4: %5")
.arg(context.file)
.arg(context.line)
.arg(context.function, context.category, logMsg);
vStdErr() << QApplication::translate("mNoisyHandler", "CRITICAL:") << logMsg << "\n";
break;
case QtFatalMsg:
debugdate += QStringLiteral(":FATAL:%1(%2)] %3: %4: %5")
.arg(context.file)
.arg(context.line)
.arg(context.function, context.category, logMsg);
vStdErr() << QApplication::translate("mNoisyHandler", "FATAL:") << logMsg << "\n";
break;
case QtInfoMsg:
debugdate += QStringLiteral(":INFO:%1(%2)] %3: %4: %5")
.arg(context.file)
.arg(context.line)
.arg(context.function, context.category, logMsg);
vStdOut() << QApplication::translate("mNoisyHandler", "INFO:") << logMsg << "\n";
break;
default:
break;
}
vStdOut().flush();
vStdErr().flush();
(*MApplication::VApp()->LogFile()) << debugdate << Qt::endl;
}
if (isGuiThread)
{
@ -247,8 +271,6 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con
messageBox.setIcon(QMessageBox::Information);
break;
case QtDebugMsg:
Q_UNREACHABLE(); //-V501
break;
default:
break;
}
@ -450,10 +472,10 @@ auto MApplication::MainTapeWindows() -> QList<TMainWindow *>
//---------------------------------------------------------------------------------------------------------------------
void MApplication::InitOptions()
{
qInstallMessageHandler(noisyFailureMsgHandler);
OpenSettings();
StartLogging();
qCDebug(mApp, "Version: %s", qUtf8Printable(AppVersionStr()));
qCDebug(mApp, "Build revision: %s", BUILD_REVISION);
qCDebug(mApp, "%s", qUtf8Printable(buildCompatibilityString()));
@ -484,6 +506,22 @@ void MApplication::InitOptions()
m_shortcutManager = new VTapeShortcutManager(this);
}
//---------------------------------------------------------------------------------------------------------------------
void MApplication::StartLogging()
{
if (CreateLogDir())
{
BeginLogging();
ClearOldLogs();
}
}
//---------------------------------------------------------------------------------------------------------------------
auto MApplication::LogFile() -> QTextStream *
{
return m_out.get();
}
//---------------------------------------------------------------------------------------------------------------------
void MApplication::InitTrVars()
{
@ -722,6 +760,38 @@ void MApplication::RestartKnownMeasurementsDatabaseWatcher()
}
}
//---------------------------------------------------------------------------------------------------------------------
auto MApplication::LogPath() -> QString
{
// Keep in sync with VCrashPaths::GetAttachmentPath
return QStringLiteral("%1/tape-pid%2.log").arg(LogDirPath()).arg(applicationPid());
}
//---------------------------------------------------------------------------------------------------------------------
void MApplication::BeginLogging()
{
VlpCreateLock(m_lockLog, LogPath(), []() { return new QFile(LogPath()); });
if (m_lockLog->IsLocked())
{
if (m_lockLog->GetProtected()->open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
{
m_out.reset(new QTextStream(m_lockLog->GetProtected().data()));
qInstallMessageHandler(noisyFailureMsgHandler);
qCDebug(mApp, "Log file %s was locked.", qUtf8Printable(LogPath()));
}
else
{
qCDebug(mApp, "Error opening log file \'%s\'. All debug output redirected to console.",
qUtf8Printable(LogPath()));
}
}
else
{
qCDebug(mApp, "Failed to lock %s", qUtf8Printable(LogPath()));
}
}
//---------------------------------------------------------------------------------------------------------------------
auto MApplication::NewMainTapeWindow() -> TMainWindow *
{

View File

@ -30,6 +30,7 @@
#define MAPPLICATION_H
#include "../vmisc/vabstractapplication.h"
#include "../vmisc/vlockguard.h"
#include "../vpatterndb/vtranslatevars.h"
#include "dialogs/dialogmdatabase.h"
#include "vtapesettings.h"
@ -71,6 +72,9 @@ public:
void InitOptions();
void StartLogging();
auto LogFile() -> QTextStream *;
auto TrVars() -> const VTranslateVars * override;
void OpenSettings() override;
@ -113,6 +117,8 @@ private:
VKnownMeasurementsDatabase *m_knownMeasurementsDatabase{nullptr};
QFileSystemWatcher *m_knownMeasurementsDatabaseWatcher{nullptr};
QFutureWatcher<void> *m_knownMeasurementsRepopulateWatcher;
QSharedPointer<VLockGuard<QFile>> m_lockLog{};
std::shared_ptr<QTextStream> m_out{nullptr};
void CleanTapeWindows();
void CleanKMWindows();
@ -131,6 +137,9 @@ private:
static void ParseUnitsOption(QCommandLineParser &parser, Unit &unit, bool &flagUnits);
void RestartKnownMeasurementsDatabaseWatcher();
static auto LogPath() -> QString;
void BeginLogging();
};
//---------------------------------------------------------------------------------------------------------------------

View File

@ -224,7 +224,7 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con
}
{
QString debugdate = "[" + QDateTime::currentDateTime().toString(QStringLiteral("yyyy.MM.dd hh:mm:ss"));
QString debugdate = "["_L1 + QDateTime::currentDateTime().toString(QStringLiteral("yyyy.MM.dd hh:mm:ss"));
switch (type)
{
@ -572,7 +572,6 @@ void VApplication::InitOptions()
{
OpenSettings();
// Run creation log after sending crash report
StartLogging();
qDebug() << "Version:" << AppVersionStr();