GODT-2015: bridge-gui logs to file until gRPC connection is established.

This commit is contained in:
Xavier Michelon
2022-11-02 17:04:25 +01:00
parent 2747e93316
commit 105752fc65
7 changed files with 83 additions and 6 deletions

View File

@ -81,6 +81,17 @@ Log &initLog()
Log &log = app().log();
log.registerAsQtMessageHandler();
log.setEchoInConsole(true);
// remove old gui log files
QDir const logsDir(userLogsDir());
for (QFileInfo const fileInfo: logsDir.entryInfoList({ "gui_v*.log" }, QDir::Filter::Files)) // entryInfolist apparently only support wildcards, not regex.
QFile(fileInfo.absoluteFilePath()).remove();
// create new GUI log file
QString error;
if (!log.startWritingToFile(logsDir.absoluteFilePath(QString("gui_v%1_%2.log").arg(PROJECT_VER).arg(QDateTime::currentSecsSinceEpoch())), &error))
log.error(error);
return log;
}
@ -278,6 +289,7 @@ int main(int argc, char *argv[])
// display it in our own output and error, so we only continue to log directly to console if we are running in attached mode.
log.setEchoInConsole(attach);
log.info("Backend was successfully initialized.");
log.stopWritingToFile();
QQmlApplicationEngine engine;
std::unique_ptr<QQmlComponent> rootComponent(createRootQmlComponent(engine));

View File

@ -133,6 +133,17 @@ QString userCacheDir()
}
//****************************************************************************************************************************************************
/// \return user logs directory used by bridge.
//****************************************************************************************************************************************************
QString userLogsDir()
{
QString const path = QDir(userCacheDir()).absoluteFilePath("logs");
QDir().mkpath(path);
return path;
}
//****************************************************************************************************************************************************
/// \return The value GOOS would return for the current platform.
//****************************************************************************************************************************************************

View File

@ -29,6 +29,7 @@ namespace bridgepp
QString userConfigDir(); ///< Get the path of the user configuration folder.
QString userCacheDir(); ///< Get the path of the user cache folder.
QString userLogsDir(); ///< Get the path of the user logs folder.
QString goos(); ///< return the value of Go's GOOS for the current platform ("darwin", "linux" and "windows" are supported).
qint64 randN(qint64 n); ///< return a random integer in the half open range [0,n)
QString randomFirstName(); ///< Get a random first name from a pre-determined list.

View File

@ -123,7 +123,7 @@ bool GRPCClient::connectToServer(GRPCConfig const &config, QString &outError)
int i = 0;
while (true)
{
this->logDebug(QString("Connection to gRPC server at %1. attempt #%2").arg(address).arg(++i));
this->logInfo(QString("Connection to gRPC server at %1. attempt #%2").arg(address).arg(++i));
if (channel_->WaitForConnected(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(grpcConnectionRetryDelayMs, GPR_TIMESPAN))))
break; // connection established.
@ -135,13 +135,13 @@ bool GRPCClient::connectToServer(GRPCConfig const &config, QString &outError)
if (channel_->GetState(true) != GRPC_CHANNEL_READY)
throw Exception("connection check failed.");
this->logDebug("Successfully connected to gRPC server.");
this->logInfo("Successfully connected to gRPC server.");
QString const clientToken = QUuid::createUuid().toString();
QString clientConfigPath = createClientConfigFile(clientToken);
if (clientConfigPath.isEmpty())
throw Exception("gRPC client config could not be saved.");
this->logDebug(QString("Client config file was saved to '%1'").arg(QDir::toNativeSeparators(clientConfigPath)));
this->logInfo(QString("Client config file was saved to '%1'").arg(QDir::toNativeSeparators(clientConfigPath)));
QString returnedClientToken;
grpc::Status status = this->checkTokens(QDir::toNativeSeparators(clientConfigPath), returnedClientToken);
@ -153,7 +153,7 @@ bool GRPCClient::connectToServer(GRPCConfig const &config, QString &outError)
if (!status.ok())
throw Exception(QString::fromStdString(status.error_message()));
log_->debug("gRPC token was validated");
log_->info("gRPC token was validated");
return true;
}
@ -933,6 +933,15 @@ void GRPCClient::logError(QString const &message)
}
//****************************************************************************************************************************************************
/// \param[in] message The event message.
//****************************************************************************************************************************************************
void GRPCClient::logInfo(QString const &message)
{
this->log(Log::Level::Info, message);
}
//****************************************************************************************************************************************************
/// \param[in] status The status
/// \param[in] callName The call name.

View File

@ -211,6 +211,8 @@ private:
void logTrace(QString const &message); ///< Log a trace event.
void logDebug(QString const &message); ///< Log a debug event.
void logError(QString const &message); ///< Log an error event.
void logInfo(QString const &message); ///< Log an info 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.
grpc::Status setBool(BoolSetter setter, bool value); ///< perform a gRPC call to a bool setter.

View File

@ -17,6 +17,7 @@
#include "Log.h"
#include "../Exception/Exception.h"
namespace bridgepp
@ -204,6 +205,35 @@ bool Log::echoInConsole() const
}
//****************************************************************************************************************************************************
/// \param[in] path The path of the file to write to.
/// \param[out] outError if an error occurs and this pointer in not null, on exit it contains a description of the error.
/// \return true if and only if the operation was successful.
//****************************************************************************************************************************************************
bool Log::startWritingToFile(QString const &path, QString *outError)
{
QMutexLocker locker(&mutex_);
file_ = std::make_unique<QFile>(path);
if (file_->open(QIODevice::WriteOnly | QIODevice::Text))
return true;
if (outError)
*outError = QString("Could not open log file '%1' for writing.");
file_.reset();
return false;
}
//****************************************************************************************************************************************************
///
//****************************************************************************************************************************************************
void Log::stopWritingToFile()
{
QMutexLocker locker(&mutex_);
file_.reset();
}
//****************************************************************************************************************************************************
/// \param[in] message The message.
//****************************************************************************************************************************************************
@ -278,12 +308,22 @@ void Log::addEntry(Log::Level level, QString const &message)
return;
emit entryAdded(level, message);
if (!(echoInConsole_ || file_))
return;
QString const entryStr = logEntryToString(level, message) + "\n";
if (echoInConsole_)
{
QTextStream &stream = (qint32(level) <= (qint32(Level::Warn))) ? stderr_ : stdout_;
stream << logEntryToString(level, message) << "\n";
stream << entryStr;
stream.flush();
}
if (file_)
{
file_->write(entryStr.toLocal8Bit());
file_->flush();
}
}

View File

@ -63,6 +63,8 @@ public: // member functions.
Level level() const; ///< Get the log level.
void setEchoInConsole(bool value); ///< Set if the log entries should be echoed in STDOUT/STDERR.
bool echoInConsole() const; ///< Check if the log entries should be echoed in STDOUT/STDERR.
bool startWritingToFile(QString const& path, QString *outError = nullptr); ///< Start writing the log to file. Concerns only future entries.
void stopWritingToFile();
void registerAsQtMessageHandler(); ///< Install the Qt message handler.
public slots:
@ -83,7 +85,7 @@ private: // data members
mutable QMutex mutex_; ///< The mutex.
Level level_ { defaultLevel }; ///< The log level
bool echoInConsole_ { false }; ///< Set if the log messages should be sent to STDOUT/STDERR.
std::unique_ptr<QFile> file_; ///< The file to write the log to.
QTextStream stdout_; ///< The stdout stream.
QTextStream stderr_; ///< The stderr stream.
};