GODT-1893: bridge-gui sends bridge's log to stdout, stderr.

WIP: bridge-gui now parses and self-apply log level from command-line.
WIP: downgraded the log level of gRPC calls to debug.
This commit is contained in:
Xavier Michelon
2022-09-26 10:03:00 +02:00
parent 7a3354f654
commit 653727fd12
13 changed files with 343 additions and 195 deletions

View File

@ -897,10 +897,10 @@ grpc::Status GRPCClient::stopEventStreamReader()
//****************************************************************************************************************************************************
/// \param[in] message The event message.
//****************************************************************************************************************************************************
void GRPCClient::logDebug(QString const &message)
void GRPCClient::logTrace(QString const &message)
{
if (log_)
log_->debug(message);
log_->trace(message);
}
@ -1102,31 +1102,31 @@ void GRPCClient::processAppEvent(AppEvent const &event)
switch (event.event_case())
{
case AppEvent::kInternetStatus:
this->logDebug("App event received: InternetStatus.");
this->logTrace("App event received: InternetStatus.");
emit internetStatus(event.internetstatus().connected());
break;
case AppEvent::kToggleAutostartFinished:
this->logDebug("App event received: AutostartFinished.");
this->logTrace("App event received: AutostartFinished.");
emit toggleAutostartFinished();
break;
case AppEvent::kResetFinished:
this->logDebug("App event received: ResetFinished.");
this->logTrace("App event received: ResetFinished.");
emit resetFinished();
break;
case AppEvent::kReportBugFinished:
this->logDebug("App event received: ReportBugFinished.");
this->logTrace("App event received: ReportBugFinished.");
emit reportBugFinished();
break;
case AppEvent::kReportBugSuccess:
this->logDebug("App event received: ReportBugSuccess.");
this->logTrace("App event received: ReportBugSuccess.");
emit reportBugSuccess();
break;
case AppEvent::kReportBugError:
this->logDebug("App event received: ReportBugError.");
this->logTrace("App event received: ReportBugError.");
emit reportBugError();
break;
case AppEvent::kShowMainWindow:
this->logDebug("App event received: ShowMainWindow.");
this->logTrace("App event received: ShowMainWindow.");
emit showMainWindow();
break;
default:
@ -1144,7 +1144,7 @@ void GRPCClient::processLoginEvent(LoginEvent const &event)
{
case LoginEvent::kError:
{
this->logDebug("Login event received: Error.");
this->logTrace("Login event received: Error.");
LoginErrorEvent const &error = event.error();
switch (error.type())
{
@ -1176,19 +1176,19 @@ void GRPCClient::processLoginEvent(LoginEvent const &event)
break;
}
case LoginEvent::kTfaRequested:
this->logDebug("Login event received: TfaRequested.");
this->logTrace("Login event received: TfaRequested.");
emit login2FARequested(QString::fromStdString(event.tfarequested().username()));
break;
case LoginEvent::kTwoPasswordRequested:
this->logDebug("Login event received: TwoPasswordRequested.");
this->logTrace("Login event received: TwoPasswordRequested.");
emit login2PasswordRequested();
break;
case LoginEvent::kFinished:
this->logDebug("Login event received: Finished.");
this->logTrace("Login event received: Finished.");
emit loginFinished(QString::fromStdString(event.finished().userid()));
break;
case LoginEvent::kAlreadyLoggedIn:
this->logDebug("Login event received: AlreadyLoggedIn.");
this->logTrace("Login event received: AlreadyLoggedIn.");
emit loginAlreadyLoggedIn(QString::fromStdString(event.finished().userid()));
break;
default:
@ -1207,7 +1207,7 @@ void GRPCClient::processUpdateEvent(UpdateEvent const &event)
{
case UpdateEvent::kError:
{
this->logDebug("Update event received: Error.");
this->logTrace("Update event received: Error.");
UpdateErrorEvent const &errorEvent = event.error();
switch (errorEvent.type())
@ -1228,31 +1228,31 @@ void GRPCClient::processUpdateEvent(UpdateEvent const &event)
break;
}
case UpdateEvent::kManualReady:
this->logDebug("Update event received: ManualReady.");
this->logTrace("Update event received: ManualReady.");
emit updateManualReady(QString::fromStdString(event.manualready().version()));
break;
case UpdateEvent::kManualRestartNeeded:
this->logDebug("Update event received: kManualRestartNeeded.");
this->logTrace("Update event received: kManualRestartNeeded.");
emit updateManualRestartNeeded();
break;
case UpdateEvent::kForce:
this->logDebug("Update event received: kForce.");
this->logTrace("Update event received: kForce.");
emit updateForce(QString::fromStdString(event.force().version()));
break;
case UpdateEvent::kSilentRestartNeeded:
this->logDebug("Update event received: kSilentRestartNeeded.");
this->logTrace("Update event received: kSilentRestartNeeded.");
emit updateSilentRestartNeeded();
break;
case UpdateEvent::kIsLatestVersion:
this->logDebug("Update event received: kIsLatestVersion.");
this->logTrace("Update event received: kIsLatestVersion.");
emit updateIsLatestVersion();
break;
case UpdateEvent::kCheckFinished:
this->logDebug("Update event received: kCheckFinished.");
this->logTrace("Update event received: kCheckFinished.");
emit checkUpdatesFinished();
break;
case UpdateEvent::kVersionChanged:
this->logDebug("Update event received: kVersionChanged.");
this->logTrace("Update event received: kVersionChanged.");
emit updateVersionChanged();
break;
default:
@ -1293,22 +1293,22 @@ void GRPCClient::processCacheEvent(CacheEvent const &event)
}
case CacheEvent::kLocationChangedSuccess:
this->logDebug("Cache event received: LocationChangedSuccess.");
this->logTrace("Cache event received: LocationChangedSuccess.");
emit cacheLocationChangeSuccess();
break;
case CacheEvent::kChangeLocalCacheFinished:
emit changeLocalCacheFinished(event.changelocalcachefinished().willrestart());
this->logDebug("Cache event received: ChangeLocalCacheFinished.");
this->logTrace("Cache event received: ChangeLocalCacheFinished.");
break;
case CacheEvent::kIsCacheOnDiskEnabledChanged:
this->logDebug("Cache event received: IsCacheOnDiskEnabledChanged.");
this->logTrace("Cache event received: IsCacheOnDiskEnabledChanged.");
emit isCacheOnDiskEnabledChanged(event.iscacheondiskenabledchanged().enabled());
break;
case CacheEvent::kDiskCachePathChanged:
this->logDebug("Cache event received: DiskCachePathChanged.");
this->logTrace("Cache event received: DiskCachePathChanged.");
emit diskCachePathChanged(QUrl::fromLocalFile(QString::fromStdString(event.diskcachepathchanged().path())));
break;
@ -1326,7 +1326,7 @@ void GRPCClient::processMailSettingsEvent(MailSettingsEvent const &event)
switch (event.event_case())
{
case MailSettingsEvent::kError:
this->logDebug("MailSettings event received: Error.");
this->logTrace("MailSettings event received: Error.");
switch (event.error().type())
{
case IMAP_PORT_ISSUE:
@ -1341,11 +1341,11 @@ void GRPCClient::processMailSettingsEvent(MailSettingsEvent const &event)
}
case MailSettingsEvent::kUseSslForSmtpFinished:
this->logDebug("MailSettings event received: UseSslForSmtpFinished.");
this->logTrace("MailSettings event received: UseSslForSmtpFinished.");
emit toggleUseSSLFinished();
break;
case MailSettingsEvent::kChangePortsFinished:
this->logDebug("MailSettings event received: ChangePortsFinished.");
this->logTrace("MailSettings event received: ChangePortsFinished.");
emit changePortFinished();
break;
default:
@ -1362,15 +1362,15 @@ void GRPCClient::processKeychainEvent(KeychainEvent const &event)
switch (event.event_case())
{
case KeychainEvent::kChangeKeychainFinished:
this->logDebug("Keychain event received: ChangeKeychainFinished.");
this->logTrace("Keychain event received: ChangeKeychainFinished.");
emit changeKeychainFinished();
break;
case KeychainEvent::kHasNoKeychain:
this->logDebug("Keychain event received: HasNoKeychain.");
this->logTrace("Keychain event received: HasNoKeychain.");
emit hasNoKeychain();
break;
case KeychainEvent::kRebuildKeychain:
this->logDebug("Keychain event received: RebuildKeychain.");
this->logTrace("Keychain event received: RebuildKeychain.");
emit rebuildKeychain();
break;
default:
@ -1387,20 +1387,20 @@ void GRPCClient::processMailEvent(MailEvent const &event)
switch (event.event_case())
{
case MailEvent::kNoActiveKeyForRecipientEvent:
this->logDebug("Mail event received: kNoActiveKeyForRecipientEvent.");
this->logTrace("Mail event received: kNoActiveKeyForRecipientEvent.");
emit noActiveKeyForRecipient(QString::fromStdString(event.noactivekeyforrecipientevent().email()));
break;
case MailEvent::kAddressChanged:
this->logDebug("Mail event received: AddressChanged.");
this->logTrace("Mail event received: AddressChanged.");
emit addressChanged(QString::fromStdString(event.addresschanged().address()));
break;
case MailEvent::kAddressChangedLogout:
this->logDebug("Mail event received: AddressChangedLogout.");
this->logTrace("Mail event received: AddressChangedLogout.");
emit addressChangedLogout(QString::fromStdString(event.addresschangedlogout().address()));
break;
case MailEvent::kApiCertIssue:
emit apiCertIssue();
this->logDebug("Mail event received: ApiCertIssue.");
this->logTrace("Mail event received: ApiCertIssue.");
break;
default:
this->logError("Unknown Mail event received.");
@ -1418,21 +1418,21 @@ void GRPCClient::processUserEvent(UserEvent const &event)
case UserEvent::kToggleSplitModeFinished:
{
QString const userID = QString::fromStdString(event.togglesplitmodefinished().userid());
this->logDebug(QString("User event received: ToggleSplitModeFinished (userID = %1).").arg(userID));
this->logTrace(QString("User event received: ToggleSplitModeFinished (userID = %1).").arg(userID));
emit toggleSplitModeFinished(userID);
break;
}
case UserEvent::kUserDisconnected:
{
QString const username = QString::fromStdString(event.userdisconnected().username());
this->logDebug(QString("User event received: UserDisconnected (username = %1).").arg(username));
this->logTrace(QString("User event received: UserDisconnected (username = %1).").arg(username));
emit userDisconnected(username);
break;
}
case UserEvent::kUserChanged:
{
QString const userID = QString::fromStdString(event.userchanged().userid());
this->logDebug(QString("User event received: UserChanged (userID = %1).").arg(userID));
this->logTrace(QString("User event received: UserChanged (userID = %1).").arg(userID));
emit userChanged(userID);
break;
}

View File

@ -203,7 +203,7 @@ private slots:
void configFolderChanged();
private:
void logDebug(QString const &message); ///< Log an event.
void logTrace(QString const &message); ///< Log an event.
void logError(QString const &message); ///< Log an event.
grpc::Status logGRPCCallStatus(grpc::Status const &status, QString const &callName, QList<grpc::StatusCode> allowedErrors = {}); ///< Log the status of a gRPC code.
grpc::Status simpleMethod(SimpleMethod method); ///< perform a gRPC call to a bool setter.

View File

@ -29,6 +29,18 @@ namespace
Log *qtHandlerLog { nullptr }; ///< The log instance handling qt logs.
QMutex qtHandlerMutex; ///< A mutex used to access qtHandlerLog.
// Mapping of log levels to string. Maybe used to lookup using both side a a key, so a list of pair is more convenient that a map.
QList<QPair<Log::Level, QString>> const logLevelStrings {
{ Log::Level::Panic, "panic", },
{ Log::Level::Fatal, "fatal", },
{ Log::Level::Error, "error", },
{ Log::Level::Warn, "warn", },
{ Log::Level::Info, "info", },
{ Log::Level::Debug, "debug", },
{ Log::Level::Trace, "trace", },
};
//****************************************************************************************************************************************************
/// \param[in] log The log handling qt log entries. Can be null.
//****************************************************************************************************************************************************
@ -79,36 +91,6 @@ void qtMessageHandler(QtMsgType type, QMessageLogContext const &, QString const
break;
}
}
//****************************************************************************************************************************************************
/// \param[in] level The level.
/// \return A string describing the level.
//****************************************************************************************************************************************************
QString logLevelToString(Log::Level level)
{
switch (level)
{
case Log::Level::Panic:
return "PANIC";
case Log::Level::Fatal:
return "FATAL";
case Log::Level::Error:
return "ERROR";
case Log::Level::Warn:
return "WARN";
case Log::Level::Info:
return "INFO";
case Log::Level::Debug:
return "DEBUG";
case Log::Level::Trace:
return "TRACE";
default:
return "UNKNOWN";
}
}
} // anonymous namespace
@ -121,7 +103,43 @@ QString logLevelToString(Log::Level level)
//****************************************************************************************************************************************************
QString Log::logEntryToString(Log::Level level, QString const &message)
{
return QString("[%1] %2").arg(logLevelToString(level), message);
return QString("[%1] %2").arg(levelToString(level).toUpper(), message);
}
//****************************************************************************************************************************************************
/// \param[in] level The level.
/// \return A string describing the level.
//****************************************************************************************************************************************************
QString Log::levelToString(Log::Level level)
{
QList<QPair<Log::Level, QString>>::const_iterator it = std::find_if(logLevelStrings.begin(), logLevelStrings.end(),
[&level](QPair<Log::Level, QString> const &pair) -> bool {
return pair.first == level;
});
return (it == logLevelStrings.end()) ? QString() : it->second;
}
//****************************************************************************************************************************************************
/// The matching is case-insensitive.
///
/// \param[in] str The string
/// \param[out] outLevel The log level parsed. if not found, the value of the variable is not modified.
/// \return true iff parsing was successful.
//****************************************************************************************************************************************************
bool Log::stringToLevel(QString const &str, Log::Level &outLevel)
{
QList<QPair<Log::Level, QString>>::const_iterator it = std::find_if(logLevelStrings.begin(), logLevelStrings.end(),
[&str](QPair<Log::Level, QString> const &pair) -> bool {
return 0 == QString::compare(str, pair.second, Qt::CaseInsensitive);
});
bool const found = (it != logLevelStrings.end());
if (found)
outLevel = it->first;
return found;
}
@ -162,7 +180,7 @@ void Log::setLevel(Log::Level level)
Log::Level Log::level() const
{
QMutexLocker locker(&mutex_);
return Log::Level::Debug;
return level_;
}

View File

@ -45,7 +45,11 @@ public: // data types.
public: // static member functions.
static QString logEntryToString(Log::Level level, QString const &message); ///< Return a string describing a log entry.
static QString levelToString(Log::Level level); ///< return the string for a level.
static bool stringToLevel(QString const &str, Log::Level& outLevel); ///< parse a level from a string.
public: // static data member.
static const Level defaultLevel { Level::Info }; ///< The default log level (the same as logrus).
public: // member functions.
Log(); ///< Default constructor.
@ -77,8 +81,8 @@ signals:
private: // data members
mutable QMutex mutex_; ///< The mutex.
Level level_{Level::Debug}; ///< The log level
bool echoInConsole_{false}; ///< Set if the log messages should be sent to STDOUT/STDERR.
Level level_ { defaultLevel }; ///< The log level
bool echoInConsole_ { false }; ///< Set if the log messages should be sent to STDOUT/STDERR.
QTextStream stdout_; ///< The stdout stream.
QTextStream stderr_; ///< The stderr stream.

View File

@ -58,11 +58,23 @@ void ProcessMonitor::run()
status_.running = true;
status_.pid = p.processId();
QTextStream out(stdout), err(stderr);
QByteArray array;
while (!p.waitForFinished(100))
{
// we discard output from bridge, it's logged to file on bridge side.
p.readAllStandardError();
p.readAllStandardOutput();
array = p.readAllStandardError();
if (!array.isEmpty())
{
err << array;
err.flush();
}
array = p.readAllStandardOutput();
if (!array.isEmpty())
{
out << array;
out.flush();
}
}
status_.running = false;