From 7bcba9850b696f37ca4a3128e22e9eaa728dfc64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Sun, 22 Sep 2024 13:14:13 +0200 Subject: [PATCH] Limit mixxx.log size to 100 MB and allow to adjust the limit via --log-max-file-size --- src/util/cmdlineargs.cpp | 24 ++++++++++++++++++++++++ src/util/cmdlineargs.h | 4 ++++ src/util/logging.cpp | 15 +++++++++++++++ src/util/logging.h | 1 + 4 files changed, 44 insertions(+) diff --git a/src/util/cmdlineargs.cpp b/src/util/cmdlineargs.cpp index 85ac74f7675..4a400c31266 100644 --- a/src/util/cmdlineargs.cpp +++ b/src/util/cmdlineargs.cpp @@ -54,6 +54,7 @@ CmdlineArgs::CmdlineArgs() m_parseForUserFeedbackRequired(false), m_logLevel(mixxx::kLogLevelDefault), m_logFlushLevel(mixxx::kLogFlushLevelDefault), + m_logMaxFileSize(mixxx::kLogMaxFileSizeDefault), // We are not ready to switch to XDG folders under Linux, so keeping $HOME/.mixxx as preferences folder. see #8090 #ifdef MIXXX_SETTINGS_PATH m_settingsPath(QDir::homePath().append("/").append(MIXXX_SETTINGS_PATH)) { @@ -286,6 +287,18 @@ bool CmdlineArgs::parse(const QStringList& arguments, CmdlineArgs::ParseMode mod parser.addOption(logFlushLevel); parser.addOption(logFlushLevelDeprecated); + const QCommandLineOption logMaxFileSize(QStringLiteral("log-max-file-size"), + forUserFeedback ? QCoreApplication::translate("CmdlineArgs", + "Sets the maximum file size of the " + "mixxx.log file in bytes. " + "Use -1 for unlimited. The default is " + "100 MB as 1e5 or 100000000.") + : QString(), + QStringLiteral("bytes")); + logFlushLevelDeprecated.setFlags(QCommandLineOption::HiddenFromHelp); + logFlushLevelDeprecated.setValueName(logFlushLevel.valueName()); + parser.addOption(logMaxFileSize); + QCommandLineOption debugAssertBreak(QStringLiteral("debug-assert-break"), forUserFeedback ? QCoreApplication::translate("CmdlineArgs", "Breaks (SIGINT) Mixxx, if a DEBUG_ASSERT evaluates to " @@ -409,6 +422,17 @@ bool CmdlineArgs::parse(const QStringList& arguments, CmdlineArgs::ParseMode mod } } + if (parser.isSet(logMaxFileSize)) { + QString strLogMaxFileSize = parser.value(logMaxFileSize); + bool ok = false; + // We parse it as double to also support exponential notation + m_logMaxFileSize = static_cast(strLogMaxFileSize.toDouble(&ok)); + if (!ok) { + fputs("\nFailed to parse log-max-file-size.\n", stdout); + return false; + } + } + // set colors if (parser.value(color).compare(QLatin1String("always"), Qt::CaseInsensitive) == 0) { m_useColors = true; diff --git a/src/util/cmdlineargs.h b/src/util/cmdlineargs.h index ec52518d33c..e52a3cda81f 100644 --- a/src/util/cmdlineargs.h +++ b/src/util/cmdlineargs.h @@ -52,6 +52,9 @@ class CmdlineArgs final { bool getSettingsPathSet() const { return m_settingsPathSet; } mixxx::LogLevel getLogLevel() const { return m_logLevel; } mixxx::LogLevel getLogFlushLevel() const { return m_logFlushLevel; } + qint64 getLogMaxFileSize() const { + return m_logMaxFileSize; + } bool getTimelineEnabled() const { return !m_timelinePath.isEmpty(); } const QString& getLocale() const { return m_locale; } const QString& getSettingsPath() const { return m_settingsPath; } @@ -91,6 +94,7 @@ class CmdlineArgs final { bool m_parseForUserFeedbackRequired; mixxx::LogLevel m_logLevel; // Level of stderr logging message verbosity mixxx::LogLevel m_logFlushLevel; // Level of mixx.log file flushing + qint64 m_logMaxFileSize; QString m_locale; QString m_settingsPath; QString m_resourcePath; diff --git a/src/util/logging.cpp b/src/util/logging.cpp index 49d95445de5..757fb92fa51 100644 --- a/src/util/logging.cpp +++ b/src/util/logging.cpp @@ -28,6 +28,8 @@ QMutex s_mutexStdErr; // The file handle for Mixxx's log file. QFile s_logfile; +qint64 s_logMaxFileSize = mixxx::kLogMaxFileSizeDefault; +bool s_logMaxFileSizeReached = false; QLoggingCategory::CategoryFilter oldCategoryFilter = nullptr; @@ -149,6 +151,10 @@ inline void writeToFile( const QString& message, const QString& threadName, bool flush) { + if (s_logMaxFileSizeReached) { + return; + } + QString formattedMessageStr = formatLogFileMessage(type, message, threadName) + QChar('\n'); @@ -158,6 +164,13 @@ inline void writeToFile( // Writing to a closed QFile could cause an infinite recursive loop // by logging to qWarning! if (s_logfile.isOpen()) { + if (s_logMaxFileSize >= 0 && s_logfile.pos() >= s_logMaxFileSize) { + formattedMessage = + "Maximum log file size reached. It can be adjusted via: " + "--log-max-file-size "; + s_logMaxFileSizeReached = true; + flush = true; + } const int written = s_logfile.write(formattedMessage); Q_UNUSED(written); DEBUG_ASSERT(written == formattedMessage.size()); @@ -434,6 +447,8 @@ void Logging::initialize( oldCategoryFilter = QLoggingCategory::installFilter(nullptr); QLoggingCategory::installFilter(controllerDebugCategoryFilter); } + + s_logMaxFileSize = CmdlineArgs::Instance().getLogMaxFileSize(); } // static diff --git a/src/util/logging.h b/src/util/logging.h index b3de7f5b821..9034ffc3598 100644 --- a/src/util/logging.h +++ b/src/util/logging.h @@ -22,6 +22,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(LogFlags); /// Default log level for (console) logs. constexpr LogLevel kLogLevelDefault = LogLevel::Warning; +constexpr qint64 kLogMaxFileSizeDefault = 100'000'000; // 100 MB /// Default log level for flushing the buffered log stream. /// This is required to ensure that all buffered messages have