diff --git a/interface/src/FileLogger.cpp b/interface/src/FileLogger.cpp index 247eb66c99..f5f7ce6ebe 100644 --- a/interface/src/FileLogger.cpp +++ b/interface/src/FileLogger.cpp @@ -12,7 +12,6 @@ #include "FileLogger.h" #include -#include #include #include @@ -25,11 +24,14 @@ static const QString FILENAME_FORMAT = "hifi-log_%1_%2.txt"; static const QString DATETIME_FORMAT = "yyyy-MM-dd_hh.mm.ss"; static const QString LOGS_DIRECTORY = "Logs"; -// Max log size is 1 MB -static const qint64 MAX_LOG_SIZE = 1024 * 1024; +// Max log size is 512 KB. We send log files to our crash reporter, so we want to keep this relatively +// small so it doesn't go over the 2MB zipped limit for all of the files we send. +static const qint64 MAX_LOG_SIZE = 512 * 1024; // Max log age is 1 hour static const uint64_t MAX_LOG_AGE_USECS = USECS_PER_SECOND * 3600; +static FilePersistThread* _persistThreadInstance; + QString getLogRollerFilename() { QString result = FileUtils::standardPath(LOGS_DIRECTORY); QHostAddress clientAddress = getGuessedLocalAddress(); @@ -43,51 +45,53 @@ const QString& getLogFilename() { return fileName; } +FilePersistThread::FilePersistThread(const FileLogger& logger) : _logger(logger) { + setObjectName("LogFileWriter"); -class FilePersistThread : public GenericQueueThread < QString > { -public: - FilePersistThread(const FileLogger& logger) : _logger(logger) { - setObjectName("LogFileWriter"); + // A file may exist from a previous run - if it does, roll the file and suppress notifying listeners. + QFile file(_logger._fileName); + if (file.exists()) { + rollFileIfNecessary(file, false); } + _lastRollTime = usecTimestampNow(); +} -protected: - void rollFileIfNecessary(QFile& file) { - uint64_t now = usecTimestampNow(); - if ((file.size() > MAX_LOG_SIZE) || (now - _lastRollTime) > MAX_LOG_AGE_USECS) { - QString newFileName = getLogRollerFilename(); - if (file.copy(newFileName)) { - _lastRollTime = now; - file.open(QIODevice::WriteOnly | QIODevice::Truncate); - file.close(); - qDebug() << "Rolled log file:" << newFileName; +void FilePersistThread::rollFileIfNecessary(QFile& file, bool notifyListenersIfRolled) { + uint64_t now = usecTimestampNow(); + if ((file.size() > MAX_LOG_SIZE) || (now - _lastRollTime) > MAX_LOG_AGE_USECS) { + QString newFileName = getLogRollerFilename(); + if (file.copy(newFileName)) { + file.open(QIODevice::WriteOnly | QIODevice::Truncate); + file.close(); + qDebug() << "Rolled log file:" << newFileName; + + if (notifyListenersIfRolled) { + emit rollingLogFile(newFileName); } + + _lastRollTime = now; } } +} - virtual bool processQueueItems(const Queue& messages) { - QFile file(_logger._fileName); - rollFileIfNecessary(file); - if (file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) { - QTextStream out(&file); - foreach(const QString& message, messages) { - out << message; - } +bool FilePersistThread::processQueueItems(const Queue& messages) { + QFile file(_logger._fileName); + rollFileIfNecessary(file); + if (file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) { + QTextStream out(&file); + foreach(const QString& message, messages) { + out << message; } - return true; } -private: - const FileLogger& _logger; - uint64_t _lastRollTime = 0; -}; - -static FilePersistThread* _persistThreadInstance; + return true; +} FileLogger::FileLogger(QObject* parent) : AbstractLoggerInterface(parent), _fileName(getLogFilename()) { _persistThreadInstance = new FilePersistThread(*this); _persistThreadInstance->initialize(true, QThread::LowestPriority); - + connect(_persistThreadInstance, &FilePersistThread::rollingLogFile, this, &FileLogger::rollingLogFile); } FileLogger::~FileLogger() { diff --git a/interface/src/FileLogger.h b/interface/src/FileLogger.h index 1053e6afa3..e9bae63a73 100644 --- a/interface/src/FileLogger.h +++ b/interface/src/FileLogger.h @@ -15,6 +15,8 @@ #include "AbstractLoggerInterface.h" #include +#include + class FileLogger : public AbstractLoggerInterface { Q_OBJECT @@ -27,11 +29,32 @@ public: virtual QString getLogData() override; virtual void locateLog() override; +signals: + void rollingLogFile(QString newFilename); + private: const QString _fileName; friend class FilePersistThread; }; +class FilePersistThread : public GenericQueueThread < QString > { + Q_OBJECT +public: + FilePersistThread(const FileLogger& logger); + +signals: + void rollingLogFile(QString newFilename); + +protected: + void rollFileIfNecessary(QFile& file, bool notifyListenersIfRolled = true); + virtual bool processQueueItems(const Queue& messages); + +private: + const FileLogger& _logger; + uint64_t _lastRollTime; +}; + + #endif // hifi_FileLogger_h diff --git a/interface/src/main.cpp b/interface/src/main.cpp index f41046f7c2..be56ad12b1 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -178,8 +178,18 @@ int main(int argc, const char* argv[]) { }); // BugSplat WILL NOT work with file paths that do not use OS native separators. - auto logPath = QDir::toNativeSeparators(app.getLogger()->getFilename()); + auto logger = app.getLogger(); + auto logPath = QDir::toNativeSeparators(logger->getFilename()); mpSender.sendAdditionalFile(qPrintable(logPath)); + + QMetaObject::Connection connection; + connection = QObject::connect(logger, &FileLogger::rollingLogFile, &app, [&mpSender, &connection](QString newFilename) { + // We only want to add the first rolled log file (the "beginning" of the log) to BugSplat to ensure we don't exceed the 2MB + // zipped limit, so we disconnect here. + QObject::disconnect(connection); + auto rolledLogPath = QDir::toNativeSeparators(newFilename); + mpSender.sendAdditionalFile(qPrintable(rolledLogPath)); + }); #endif printSystemInformation();