Index: sources/storage/Logger.cpp =================================================================== diff -u -r2eb6b48bc7153389e2e4a0216e3e3ffce2540da1 -r8566686e033eaa3025180a735ce6f485e4fcaad4 --- sources/storage/Logger.cpp (.../Logger.cpp) (revision 2eb6b48bc7153389e2e4a0216e3e3ffce2540da1) +++ sources/storage/Logger.cpp (.../Logger.cpp) (revision 8566686e033eaa3025180a735ce6f485e4fcaad4) @@ -1,13 +1,13 @@ /*! * - * Copyright (c) 2020-2023 Diality Inc. - All Rights Reserved. + * Copyright (c) 2020-2024 Diality Inc. - All Rights Reserved. * \copyright * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * \file Logger.cpp - * \author (last) Behrouz NematiPour - * \date (last) 14-Aug-2023 + * \author (last) Dara Navaei + * \date (last) 07-Feb-2024 * \author (original) Behrouz NematiPour * \date (original) 26-Aug-2020 * @@ -24,6 +24,7 @@ #include // Project +#include "ApplicationController.h" #include "DeviceController.h" #include "Threads.h" #include "StorageGlobals.h" @@ -40,7 +41,9 @@ * Qt handles the children destruction by their parent objects life-cycle. */ Logger::Logger(QObject *parent) : QObject(parent) { - _logFileNamePrefix = QFileInfo(qApp->applicationFilePath()).baseName(); + if ( ! gLongLogName ) { + _fileDateFormat = "yyyy_MM_dd"; // date used in the file name + } } /*! @@ -130,6 +133,9 @@ */ void Logger::initConnections() { + connect(&_ApplicationController , SIGNAL(didActionReceive (GuiActionType , const QVariantList &)), + this , SLOT( onActionReceive (GuiActionType , const QVariantList &))); + connect(&_exportLogsWatcher, SIGNAL(finished ()), this , SLOT(onExportLogs())); @@ -234,7 +240,7 @@ #endif if (vUseTempPath) { - _dir.setPath(Storage::Standard_tmp); + _dir.setPath(gStandard_tmp); // NOTE: Do not use LOG_XXXXX, At this moment Logger has not been initialized yet QString msg = QString("temp location used for events logging (%1)").arg(_dir.path()); //DEBUG qDebug() << msg; @@ -260,8 +266,8 @@ /*! * \brief Logger::onCryptSetupMount - * \details the handlet for the _DeviceController::didCryptSetupMount - * to set the treatment fodler when the encrypted parttion is ready + * \details the handler for the _DeviceController::didCryptSetupMount + * to set the treatment folder when the encrypted partition is ready * and successfully decrypted and mounted. * It checks to make sure the folder exist and is able to be written and read. */ @@ -271,11 +277,11 @@ QString basePath = Storage::Settings_Path(); // use the Settings path first (/var/configurations (Encrypted Partition)) - if ( ! QDir (basePath ).exists( )) { basePath = Storage::Standard_tmp; goto lOut; } - if ( ! FileHandler::makeFolder (basePath + Storage::Log_Folder_Treatment )) { basePath = Storage::Standard_tmp; goto lOut; } + if ( ! QDir (basePath ).exists( )) { basePath = gStandard_tmp; goto lOut; } + if ( ! FileHandler::makeFolder (basePath + Storage::Txr_Folder_Treatment )) { basePath = gStandard_tmp; goto lOut; } lOut: - _logPathNames[vLogType] = basePath + Storage::Log_Folder_Treatment; + _logPathNames[vLogType] = basePath + Storage::Txr_Folder_Treatment; emit didLogPathSet(vLogType, _logPathNames[vLogType]); FileHandler::errOut(tr("The '%1' folder selected for the treatment reports").arg(_logPathNames[vLogType])); @@ -313,13 +319,12 @@ { if ( ! checkThread() ) return; - static QString date; QString mContent; // - Add header - QString currentDate = QDate::currentDate().toString(_dateFormat); - if ( date != currentDate ) { - if ( ! date.isEmpty() ) { + QString currentDate = QDate::currentDate().toString(_fileDateFormat); + if ( _logFileNameDate != currentDate ) { + if ( ! _logFileNameDate.isEmpty() ) { switch ( vLogType ) { case eLogAppED : mContent = _headerA; break; case eLogDebug : mContent = _headerD; break; @@ -328,17 +333,59 @@ } mContent += "\r\n"; } - date = currentDate; + _logFileNameDate = currentDate; } // - Make log file name - QString fileName = date + _dateSeparator + _logFileNamePrefix; - switch (vLogType) { - case LogType::eLogAppED: - case LogType::eLogDebug: + if (_logFileNameMode.isEmpty()) { + _logFileNameMode = _logFileNameMode_init; + _logFileNameTime = QDateTime::currentDateTime().time().toString(_fileTimeFormat); + } + + QString fileName; + if ( ! gLongLogName ) { + fileName = _logFileNameDate + + _fileSeparator + "denali"; + } + else { + fileName = _logFileNameDate + + _fileSeparator + _logFileNameTime + + _fileSeparator + _logFileNameHDSN + + _fileSeparator + _logFileNameMode + ; + } // case LogType::eLogTrtmt: // this type of log will never happen here. Only put here to make sure it is intentional. - fileName += _logFileNameExt[vLogType]; + switch (vLogType) { + case LogType::eLogAppED: { + // ------------------------------------------------------------------------ TODO: Improve : function declaration + fileName += _logFileNameExt[vLogType]; + static QString oFileName; + if( oFileName != fileName ) { + if( oFileName.trimmed().isEmpty() ) { + oFileName = fileName; + } + else { + emit didLogBackup( _logPathNames[vLogType] + oFileName ); + oFileName = fileName; + } + } + } break; + case LogType::eLogDebug: { + // ------------------------------------------------------------------------ TODO: Improve : function declaration + fileName += _logFileNameExt[vLogType]; + static QString oFileName; + if( oFileName != fileName ) { + if( oFileName.trimmed().isEmpty() ) { + oFileName = fileName; + } + else { + emit didLogBackup( _logPathNames[vLogType] + oFileName ); + oFileName = fileName; + } + } + } + break; default: fileName += _logFileNameExt[eLogDebug]; @@ -375,7 +422,7 @@ * into USB drive folder (Storage::USB_Mount_Point) * \return true if at least one file has been exported */ -bool Logger::exportLogs(const Gui::GuiStringIndexMap &vExportList) +bool Logger::exportLogs(const GuiStringIndexMap &vExportList) { return exportList(vExportList, eLogAppED); } @@ -386,7 +433,7 @@ * into USB drive folder (Storage::USB_Mount_Point) * \return true if at least one file has been exported */ -bool Logger::exportErrs(const Gui::GuiStringIndexMap &vExportList) +bool Logger::exportErrs(const GuiStringIndexMap &vExportList) { return exportList(vExportList, eLogDebug); } @@ -397,7 +444,7 @@ * into USB drive folder (Storage::USB_Mount_Point) * \return true if at least one file has been exported */ -bool Logger::exportTrts(const Gui::GuiStringIndexMap &vExportList) +bool Logger::exportTrts(const GuiStringIndexMap &vExportList) { return exportList(vExportList, eLogTrtmt); } @@ -422,7 +469,7 @@ * \return always returns true for now. * \note This method uses QtConcurrent run to execute the FileHandler copyFolder method. */ -bool Logger::concurrentExportLogs(const Gui::GuiStringIndexMap &vExportList) +bool Logger::concurrentExportLogs(const GuiStringIndexMap &vExportList) { if ( ! concurrentExportIsOk() ) return false; @@ -439,7 +486,7 @@ * \return always returns true for now. * \note This method uses QtConcurrent run to execute the FileHandler copyFolder method. */ -bool Logger::concurrentExportErrs(const Gui::GuiStringIndexMap &vExportList) +bool Logger::concurrentExportErrs(const GuiStringIndexMap &vExportList) { if ( ! concurrentExportIsOk() ) return false; @@ -456,7 +503,7 @@ * \return always returns true for now. * \note This method uses QtConcurrent run to execute the FileHandler copyFolder method. */ -bool Logger::concurrentExportTrts(const Gui::GuiStringIndexMap &vExportList) +bool Logger::concurrentExportTrts(const GuiStringIndexMap &vExportList) { if ( ! concurrentExportIsOk() ) return false; @@ -487,48 +534,122 @@ // disabled coco end /*! + * \brief CloudSyncController::onActionReceive + * \details The slot which will be called when a CANBus message is received, and will be sent to CloudSync if related. + * \param vAction - The message action + * \param vData - The message data + */ +void Logger::onActionReceive(GuiActionType vAction, const QVariantList &vData) +{ + switch (vAction) { + case GuiActionType::ID_HDOperationModeData : { + if ( vData.length() >= 2 ) { + bool ok = true; + quint32 opMode = vData[0].toUInt(&ok); if ( ! ok ) return; + quint32 subMode = vData[1].toUInt(&ok); if ( ! ok ) return; + QString mode; + if ( opMode == GuiHDOpModes::MODE_STAN && subMode >= GuiHDStandbyStates::STANDBY_WAIT_FOR_DISINFECT_STATE ) { + mode = "Disinfect"; + if( _logFileNameMode != mode ) { + _logFileNameMode = mode; + _logFileNameTime = QDateTime::currentDateTime().time().toString(_fileTimeFormat); + } + } + else { + switch ( opMode ) { + case GuiHDOpModes::MODE_NLEG: + case GuiHDOpModes::MODE_FAUL: + case GuiHDOpModes::MODE_SERV: + case GuiHDOpModes::MODE_INIT: + case GuiHDOpModes::MODE_STAN: + mode = _logFileNameMode_init; + if( _logFileNameMode != mode ) { + _logFileNameMode = mode; + _logFileNameTime = QDateTime::currentDateTime().time().toString(_fileTimeFormat); + } + break; + case GuiHDOpModes::MODE_TPAR: + case GuiHDOpModes::MODE_PRET: + case GuiHDOpModes::MODE_TREA: + case GuiHDOpModes::MODE_POST: + mode = "Treatment"; + if( _logFileNameMode != mode ) { + _logFileNameMode = mode; + _logFileNameTime = QDateTime::currentDateTime().time().toString(_fileTimeFormat); + } + break; + + default: + break; + } + break; + } + } + } + break; + + case GuiActionType::ID_AdjustSerialHDRsp : { + if ( vData.length() >= 1 ) { + QString hdSerial= vData[0].toString(); + if ( hdSerial.trimmed().isEmpty() ) hdSerial = "Unknown"; + _logFileNameHDSN = hdSerial; + } + } + break; + + default: + break; + } +} + +/*! * \brief Logger::removeLogs * \details Remove old logs by iterating in the log/service folders and look for expired logs. * \return count file(s) have been removed. */ -int Logger::removeLogs() +int Logger::removeLogs(LogType vLogType) { // Storage::FileHandler::find("/media/denali/0CAA-40C1/log/", {"*.err"}, 15); return 0; // has been tested manually LOG_DEBUG(tr("Initializing log clean up")); int removeCount = 0; - for ( const auto &iType : { eLogAppED , eLogDebug , eLogTrtmt } ) { + auto logFiles = { eLogAppED , eLogDebug , eLogCloud }; // TODO: UI (Linux denali user has no access to the CloudSync log folders to delete) + auto logFile = { vLogType }; // Is mostly used for the txr files which are in separate partition. + + for ( const auto &iType : ( vLogType == eLogFiles ? logFiles : logFile ) ) { QString mCSource = _logPathNames [iType]; QString mCExtension = _logFileNameExt[iType]; // DEBUG: qDebug() << "@" << mCSource << mLogFileFilter << mCExtension << iType << _logTypeMaxUsageLimit[iType]; - QFileInfoList fileInfoList = FileHandler::find(mCSource, {"*.*"}, _logTypeMaxUsageLimit[iType]); + QFileInfoList fileInfoList = FileHandler::find( + mCSource , // where to look + {"*.*"} , // what to delete // it means the removal will be for all the files in that location and won't look at the mCExtension + _logTypeMaxUsageLimit[iType]); // how many/much removeCount = fileInfoList.count(); // qDebug() << "@" << removeCount << fileInfoList; - if (removeCount) { - LOG_DEBUG(QString("Removing %1 logs of type (%2) more than %3% limit from folder %4") - .arg(removeCount) - .arg(mCExtension) - .arg(_logTypeMaxUsageLimit[iType]) - .arg(mCSource)); - for (const auto &info: fileInfoList) { - if (info.lastModified().date() == QDate().currentDate()) { - LOG_DEBUG(QString("Current day log %1 cannot be deleted").arg(info.fileName())); - } - else { - QString mFileName = mCSource + info.fileName(); - // DEBUG: qDebug() << "#" << mFileName; - bool ok = QFile::remove(mFileName); - if (ok) { - LOG_DEBUG(QString("Removing %1 succeeded").arg(mFileName)); - } else { - LOG_DEBUG(QString("Removing %1 failed" ).arg(mFileName)); - } - } + if ( ! removeCount ) { LOG_DEBUG(QString("No log file to delete for type(%1) more than %2% limit from folder %3") + .arg(mCExtension) + .arg(_logTypeMaxUsageLimit[iType]) + .arg(mCSource)); continue; } + LOG_DEBUG(QString("Removing %1 logs of type (%2) more than %3% limit from folder %4") + .arg(removeCount) + .arg(mCExtension) + .arg(_logTypeMaxUsageLimit[iType]) + .arg(mCSource)); + for (const auto &info: fileInfoList) { + bool isWritable = info.isWritable(); + bool isOldLog = info.lastModified().date() != QDate().currentDate(); + if ( ! isWritable ) { LOG_DEBUG(QString("Log %1 cannot be deleted" ).arg(info.fileName())); continue; } + if ( ! isOldLog ) { LOG_DEBUG(QString("Current day log %1 cannot be deleted" ).arg(info.fileName())); continue; } + + QString mFileName = mCSource + info.fileName(); + // DEBUG: qDebug() << "#" << mFileName; + bool ok = QFile::remove(mFileName); + if (ok) { + LOG_DEBUG(QString("Removing %1 succeeded").arg(mFileName)); + } else { + LOG_DEBUG(QString("Removing %1 failed" ).arg(mFileName)); } } - else { - LOG_DEBUG("No log file is deleted for " + mCExtension); - } } return removeCount; } @@ -539,13 +660,13 @@ * \return always returns true for now. * \note This method uses QtConcurrent run to execute the FileHandler copyFolder method. */ -bool Logger::concurrentRemoveLogs() +bool Logger::concurrentRemoveLogs(LogType vLogType) { // disabled coco begin validated: This needs user interaction to check the old files deleted // has been tested manually LOG_DEBUG("Remove Logs Starting"); emit didRemoveLogs(true); - QFuture mFuture = QtConcurrent::run(this, &Logger::removeLogs); + QFuture mFuture = QtConcurrent::run(this, &Logger::removeLogs, vLogType); _removeLogsWatcher.setFuture(mFuture); return true; } @@ -607,14 +728,8 @@ */ void Logger::onSettingsPartitionStateChange(bool vReady, bool vReadonly) { -#if BUILD_FOR_DESKTOP - Q_UNUSED(vReady ) - Q_UNUSED(vReadonly ) - _logStorageReady = true; -#else - // Include settings partition state - _logStorageReady = _logStorageReady && vReady && !vReadonly; -#endif + Q_UNUSED(vReadonly) + LOG_DEBUG(QString("Settings Partition State Changed | vReady: %1 ").arg(vReady)); } /*! @@ -637,8 +752,8 @@ if ( ! vReady ) return; // DEBUG: qDebug() << vPercent << Storage::Available_Space_Percent; - if ( Storage::Log_Min_Available_Total_Space_IsLow(vPercent) ) { - concurrentRemoveLogs(); + if ( Storage::Txr_Min_Available_Total_Space_IsLow(vPercent) ) { + concurrentRemoveLogs(eLogTrtmt); } } // disabled coco end @@ -680,7 +795,7 @@ * \param vLogType - type of the log files to get the correct location for export. * \return true if the export is successful. */ -bool Logger::exportList(const Gui::GuiStringIndexMap &vExportList, Logger::LogType vLogType) +bool Logger::exportList(const GuiStringIndexMap &vExportList, Logger::LogType vLogType) { // DEBUG: qDebug() << __FUNCTION__ << vExportList; // qDebug() << " ~~~~~~~~~~ " << QThread::currentThread()->objectName(); @@ -698,7 +813,7 @@ result = FileHandler::copyFolder( mSource, mDestination); } else { - Gui::GuiStringIndexMapIterator it(vExportList); + GuiStringIndexMapIterator it(vExportList); while ( it.hasNext() ) { it.next(); // qDebug() << it.key() << it.value() << mSource << mDestination;