forked from Silverfish/proton-bridge
feat(GODT-2690): update sentry reporting in GUI for new log file naming.
This commit is contained in:
@ -117,7 +117,27 @@ void AppController::restart(bool isCrashing) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
/// \param[in] launcher The launcher.
|
||||||
|
/// \param[in] args The launcher arguments.
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
void AppController::setLauncherArgs(const QString &launcher, const QStringList &args) {
|
void AppController::setLauncherArgs(const QString &launcher, const QStringList &args) {
|
||||||
launcher_ = launcher;
|
launcher_ = launcher;
|
||||||
launcherArgs_ = args;
|
launcherArgs_ = args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
/// \param[in] sessionID The sessionID.
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
void AppController::setSessionID(const QString &sessionID) {
|
||||||
|
sessionID_ = sessionID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
/// \return The sessionID.
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
QString AppController::sessionID() {
|
||||||
|
return sessionID_;
|
||||||
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ class Exception;
|
|||||||
/// \brief App controller class.
|
/// \brief App controller class.
|
||||||
//****************************************************************************************************************************************************
|
//****************************************************************************************************************************************************
|
||||||
class AppController : public QObject {
|
class AppController : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
friend AppController &app();
|
friend AppController &app();
|
||||||
|
|
||||||
public: // member functions.
|
public: // member functions.
|
||||||
@ -52,10 +52,12 @@ public: // member functions.
|
|||||||
std::unique_ptr<bridgepp::Overseer> &bridgeOverseer() { return bridgeOverseer_; }; ///< Returns a reference the bridge overseer
|
std::unique_ptr<bridgepp::Overseer> &bridgeOverseer() { return bridgeOverseer_; }; ///< Returns a reference the bridge overseer
|
||||||
bridgepp::ProcessMonitor *bridgeMonitor() const; ///< Return the bridge worker.
|
bridgepp::ProcessMonitor *bridgeMonitor() const; ///< Return the bridge worker.
|
||||||
Settings &settings();; ///< Return the application settings.
|
Settings &settings();; ///< Return the application settings.
|
||||||
void setLauncherArgs(const QString &launcher, const QStringList &args);
|
void setLauncherArgs(const QString &launcher, const QStringList &args); ///< Set the launcher arguments.
|
||||||
|
void setSessionID(QString const &sessionID); ///< Set the sessionID.
|
||||||
|
QString sessionID(); ///< Get the sessionID.
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void onFatalError(bridgepp::Exception const& e); ///< Handle fatal errors.
|
void onFatalError(bridgepp::Exception const &e); ///< Handle fatal errors.
|
||||||
|
|
||||||
private: // member functions
|
private: // member functions
|
||||||
AppController(); ///< Default constructor.
|
AppController(); ///< Default constructor.
|
||||||
@ -67,8 +69,9 @@ private: // data members
|
|||||||
std::unique_ptr<bridgepp::Log> log_; ///< The log.
|
std::unique_ptr<bridgepp::Log> log_; ///< The log.
|
||||||
std::unique_ptr<bridgepp::Overseer> bridgeOverseer_; ///< The overseer for the bridge monitor worker.
|
std::unique_ptr<bridgepp::Overseer> bridgeOverseer_; ///< The overseer for the bridge monitor worker.
|
||||||
std::unique_ptr<Settings> settings_; ///< The application settings.
|
std::unique_ptr<Settings> settings_; ///< The application settings.
|
||||||
QString launcher_;
|
QString launcher_; ///< The launcher.
|
||||||
QStringList launcherArgs_;
|
QStringList launcherArgs_; ///< The launcher arguments.
|
||||||
|
QString sessionID_; ///< The sessionID.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -143,12 +143,14 @@ CommandLineOptions parseCommandLine(int argc, char *argv[]) {
|
|||||||
|
|
||||||
options.logLevel = parseLogLevel(argc, argv);
|
options.logLevel = parseLogLevel(argc, argv);
|
||||||
|
|
||||||
options.sessionID = parseGoCLIStringArgument(argc, argv, { "session-id" });
|
QString sessionID = parseGoCLIStringArgument(argc, argv, { "session-id" });
|
||||||
if (options.sessionID.isEmpty()) {
|
if (sessionID.isEmpty()) {
|
||||||
options.sessionID = newSessionID();
|
// The session ID was not passed to us on the command-line -> create one and add to the command-line for bridge
|
||||||
|
sessionID = newSessionID();
|
||||||
options.bridgeArgs.append("--session-id");
|
options.bridgeArgs.append("--session-id");
|
||||||
options.bridgeArgs.append(options.sessionID);
|
options.bridgeArgs.append(sessionID);
|
||||||
}
|
}
|
||||||
|
app().setSessionID(sessionID);
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,7 +34,6 @@ struct CommandLineOptions {
|
|||||||
bridgepp::Log::Level logLevel { bridgepp::Log::defaultLevel }; ///< The log level
|
bridgepp::Log::Level logLevel { bridgepp::Log::defaultLevel }; ///< The log level
|
||||||
bool noWindow { false }; ///< Should the application start without displaying the main window?
|
bool noWindow { false }; ///< Should the application start without displaying the main window?
|
||||||
bool useSoftwareRenderer { false }; ///< Should QML be renderer in software (i.e. without rendering hardware interface).
|
bool useSoftwareRenderer { false }; ///< Should QML be renderer in software (i.e. without rendering hardware interface).
|
||||||
QString sessionID; ///< The sessionID.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -27,20 +27,15 @@ using namespace bridgepp;
|
|||||||
//****************************************************************************************************************************************************
|
//****************************************************************************************************************************************************
|
||||||
/// \return A reference to the log.
|
/// \return A reference to the log.
|
||||||
//****************************************************************************************************************************************************
|
//****************************************************************************************************************************************************
|
||||||
Log &initLog(QString const &sessionID) {
|
Log &initLog() {
|
||||||
Log &log = app().log();
|
Log &log = app().log();
|
||||||
log.registerAsQtMessageHandler();
|
log.registerAsQtMessageHandler();
|
||||||
log.setEchoInConsole(true);
|
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
|
// create new GUI log file
|
||||||
QString error;
|
QString error;
|
||||||
if (!log.startWritingToFile(logsDir.absoluteFilePath(QString("%1_gui_000_v%2_%3.log").arg(sessionID, PROJECT_VER, PROJECT_TAG)), &error)) {
|
if (!log.startWritingToFile(QDir(userLogsDir()).absoluteFilePath(QString("%1_gui_000_v%2_%3.log").arg(app().sessionID(),
|
||||||
|
PROJECT_VER, PROJECT_TAG)), &error)) {
|
||||||
log.error(error);
|
log.error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,7 @@
|
|||||||
#include <bridgepp/Log/Log.h>
|
#include <bridgepp/Log/Log.h>
|
||||||
|
|
||||||
|
|
||||||
bridgepp::Log &initLog(QString const &sessionID); ///< Initialize the application log.
|
bridgepp::Log &initLog(); ///< Initialize the application log.
|
||||||
|
|
||||||
|
|
||||||
#endif //BRIDGE_GUI_LOG_UTILS_H
|
#endif //BRIDGE_GUI_LOG_UTILS_H
|
||||||
|
|||||||
@ -61,7 +61,7 @@ void QMLBackend::init(GRPCConfig const &serviceConfig) {
|
|||||||
app().grpc().setLog(&log);
|
app().grpc().setLog(&log);
|
||||||
this->connectGrpcEvents();
|
this->connectGrpcEvents();
|
||||||
|
|
||||||
app().grpc().connectToServer(bridgepp::userConfigDir(), serviceConfig, app().bridgeMonitor());
|
app().grpc().connectToServer(app().sessionID(), bridgepp::userConfigDir(), serviceConfig, app().bridgeMonitor());
|
||||||
app().log().info("Connected to backend via gRPC service.");
|
app().log().info("Connected to backend via gRPC service.");
|
||||||
|
|
||||||
QString bridgeVer;
|
QString bridgeVer;
|
||||||
@ -640,7 +640,7 @@ void QMLBackend::login(QString const &username, QString const &password) const {
|
|||||||
HANDLE_EXCEPTION(
|
HANDLE_EXCEPTION(
|
||||||
if (username.compare("coco@bandicoot", Qt::CaseInsensitive) == 0) {
|
if (username.compare("coco@bandicoot", Qt::CaseInsensitive) == 0) {
|
||||||
throw Exception("User requested bridge-gui to crash by trying to log as coco@bandicoot",
|
throw Exception("User requested bridge-gui to crash by trying to log as coco@bandicoot",
|
||||||
"This error exists for test purposes and should be ignored.", __func__, tailOfLatestBridgeLog());
|
"This error exists for test purposes and should be ignored.", __func__, tailOfLatestBridgeLog(app().sessionID()));
|
||||||
}
|
}
|
||||||
app().grpc().login(username, password);
|
app().grpc().login(username, password);
|
||||||
)
|
)
|
||||||
|
|||||||
@ -287,7 +287,7 @@ int main(int argc, char *argv[]) {
|
|||||||
initQtApplication();
|
initQtApplication();
|
||||||
|
|
||||||
CommandLineOptions const cliOptions = parseCommandLine(argc, argv);
|
CommandLineOptions const cliOptions = parseCommandLine(argc, argv);
|
||||||
Log &log = initLog(cliOptions.sessionID);
|
Log &log = initLog();
|
||||||
|
|
||||||
QLockFile lock(bridgepp::userCacheDir() + "/" + bridgeGUILock);
|
QLockFile lock(bridgepp::userCacheDir() + "/" + bridgeGUILock);
|
||||||
if (!checkSingleInstance(lock)) {
|
if (!checkSingleInstance(lock)) {
|
||||||
@ -306,22 +306,23 @@ int main(int argc, char *argv[]) {
|
|||||||
log.setLevel(cliOptions.logLevel);
|
log.setLevel(cliOptions.logLevel);
|
||||||
log.info(QString("New Sentry reporter - id: %1.").arg(getProtectedHostname()));
|
log.info(QString("New Sentry reporter - id: %1.").arg(getProtectedHostname()));
|
||||||
|
|
||||||
QString bridgeexec;
|
QString const &sessionID = app().sessionID();
|
||||||
|
QString bridgeExe;
|
||||||
if (!cliOptions.attach) {
|
if (!cliOptions.attach) {
|
||||||
if (isBridgeRunning()) {
|
if (isBridgeRunning()) {
|
||||||
throw Exception("An orphan instance of bridge is already running. Please terminate it and relaunch the application.",
|
throw Exception("An orphan instance of bridge is already running. Please terminate it and relaunch the application.",
|
||||||
QString(), __FUNCTION__, tailOfLatestBridgeLog());
|
QString(), __FUNCTION__, tailOfLatestBridgeLog(sessionID));
|
||||||
}
|
}
|
||||||
|
|
||||||
// before launching bridge, we remove any trailing service config file, because we need to make sure we get a newly generated one.
|
// before launching bridge, we remove any trailing service config file, because we need to make sure we get a newly generated one.
|
||||||
FocusGRPCClient::removeServiceConfigFile(configDir);
|
FocusGRPCClient::removeServiceConfigFile(configDir);
|
||||||
GRPCClient::removeServiceConfigFile(configDir);
|
GRPCClient::removeServiceConfigFile(configDir);
|
||||||
bridgeexec = launchBridge(cliOptions.bridgeArgs);
|
bridgeExe = launchBridge(cliOptions.bridgeArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info(QString("Retrieving gRPC service configuration from '%1'").arg(QDir::toNativeSeparators(grpcServerConfigPath(configDir))));
|
log.info(QString("Retrieving gRPC service configuration from '%1'").arg(QDir::toNativeSeparators(grpcServerConfigPath(configDir))));
|
||||||
app().backend().init(GRPCClient::waitAndRetrieveServiceConfig(configDir, cliOptions.attach ? 0 : grpcServiceConfigWaitDelayMs,
|
app().backend().init(GRPCClient::waitAndRetrieveServiceConfig(sessionID, configDir,
|
||||||
app().bridgeMonitor()));
|
cliOptions.attach ? 0 : grpcServiceConfigWaitDelayMs, app().bridgeMonitor()));
|
||||||
if (!cliOptions.attach) {
|
if (!cliOptions.attach) {
|
||||||
GRPCClient::removeServiceConfigFile(configDir);
|
GRPCClient::removeServiceConfigFile(configDir);
|
||||||
}
|
}
|
||||||
@ -379,9 +380,9 @@ int main(int argc, char *argv[]) {
|
|||||||
QStringList args = cliOptions.bridgeGuiArgs;
|
QStringList args = cliOptions.bridgeGuiArgs;
|
||||||
args.append(waitFlag);
|
args.append(waitFlag);
|
||||||
args.append(mainexec);
|
args.append(mainexec);
|
||||||
if (!bridgeexec.isEmpty()) {
|
if (!bridgeExe.isEmpty()) {
|
||||||
args.append(waitFlag);
|
args.append(waitFlag);
|
||||||
args.append(bridgeexec);
|
args.append(bridgeExe);
|
||||||
}
|
}
|
||||||
app().setLauncherArgs(cliOptions.launcher, args);
|
app().setLauncherArgs(cliOptions.launcher, args);
|
||||||
result = QGuiApplication::exec();
|
result = QGuiApplication::exec();
|
||||||
|
|||||||
@ -57,11 +57,13 @@ void GRPCClient::removeServiceConfigFile(QString const &configDir) {
|
|||||||
|
|
||||||
|
|
||||||
//****************************************************************************************************************************************************
|
//****************************************************************************************************************************************************
|
||||||
|
/// \param[in] sessionID The sessionID.
|
||||||
/// \param[in] timeoutMs The timeout in milliseconds
|
/// \param[in] timeoutMs The timeout in milliseconds
|
||||||
/// \param[in] serverProcess An optional server process to monitor. If the process it, no need and retry, as connexion cannot be established. Ignored if null.
|
/// \param[in] serverProcess An optional server process to monitor. If the process it, no need and retry, as connexion cannot be established. Ignored if null.
|
||||||
/// \return The service config.
|
/// \return The service config.
|
||||||
//****************************************************************************************************************************************************
|
//****************************************************************************************************************************************************
|
||||||
GRPCConfig GRPCClient::waitAndRetrieveServiceConfig(QString const &configDir, qint64 timeoutMs, ProcessMonitor *serverProcess) {
|
GRPCConfig GRPCClient::waitAndRetrieveServiceConfig(QString const & sessionID, QString const &configDir, qint64 timeoutMs,
|
||||||
|
ProcessMonitor *serverProcess) {
|
||||||
QString const path = grpcServerConfigPath(configDir);
|
QString const path = grpcServerConfigPath(configDir);
|
||||||
QFile file(path);
|
QFile file(path);
|
||||||
|
|
||||||
@ -71,7 +73,7 @@ GRPCConfig GRPCClient::waitAndRetrieveServiceConfig(QString const &configDir, qi
|
|||||||
while (true) {
|
while (true) {
|
||||||
if (serverProcess && serverProcess->getStatus().ended) {
|
if (serverProcess && serverProcess->getStatus().ended) {
|
||||||
throw Exception("Bridge application exited before providing a gRPC service configuration file.", QString(), __FUNCTION__,
|
throw Exception("Bridge application exited before providing a gRPC service configuration file.", QString(), __FUNCTION__,
|
||||||
tailOfLatestBridgeLog());
|
tailOfLatestBridgeLog(sessionID));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
@ -85,7 +87,7 @@ GRPCConfig GRPCClient::waitAndRetrieveServiceConfig(QString const &configDir, qi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
throw Exception("Server did not provide gRPC service configuration in time.", QString(), __FUNCTION__, tailOfLatestBridgeLog());
|
throw Exception("Server did not provide gRPC service configuration in time.", QString(), __FUNCTION__, tailOfLatestBridgeLog(sessionID));
|
||||||
}
|
}
|
||||||
|
|
||||||
GRPCConfig sc;
|
GRPCConfig sc;
|
||||||
@ -114,10 +116,12 @@ void GRPCClient::setLog(Log *log) {
|
|||||||
|
|
||||||
|
|
||||||
//****************************************************************************************************************************************************
|
//****************************************************************************************************************************************************
|
||||||
|
/// \param[in] sessionID The sessionID.
|
||||||
|
/// \param[in] configDir The configuration directory
|
||||||
/// \param[in] serverProcess An optional server process to monitor. If the process it, no need and retry, as connexion cannot be established. Ignored if null.
|
/// \param[in] serverProcess An optional server process to monitor. If the process it, no need and retry, as connexion cannot be established. Ignored if null.
|
||||||
/// \return true iff the connection was successful.
|
/// \return true iff the connection was successful.
|
||||||
//****************************************************************************************************************************************************
|
//****************************************************************************************************************************************************
|
||||||
void GRPCClient::connectToServer(QString const &configDir, GRPCConfig const &config, ProcessMonitor *serverProcess) {
|
void GRPCClient::connectToServer(QString const &sessionID, QString const &configDir, GRPCConfig const &config, ProcessMonitor *serverProcess) {
|
||||||
try {
|
try {
|
||||||
serverToken_ = config.token.toStdString();
|
serverToken_ = config.token.toStdString();
|
||||||
QString address;
|
QString address;
|
||||||
@ -147,7 +151,7 @@ void GRPCClient::connectToServer(QString const &configDir, GRPCConfig const &con
|
|||||||
while (true) {
|
while (true) {
|
||||||
if (serverProcess && serverProcess->getStatus().ended) {
|
if (serverProcess && serverProcess->getStatus().ended) {
|
||||||
throw Exception("Bridge application ended before gRPC connexion could be established.", QString(), __FUNCTION__,
|
throw Exception("Bridge application ended before gRPC connexion could be established.", QString(), __FUNCTION__,
|
||||||
tailOfLatestBridgeLog());
|
tailOfLatestBridgeLog(sessionID));
|
||||||
}
|
}
|
||||||
|
|
||||||
this->logInfo(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));
|
||||||
@ -158,7 +162,7 @@ void GRPCClient::connectToServer(QString const &configDir, GRPCConfig const &con
|
|||||||
|
|
||||||
if (QDateTime::currentDateTime() > giveUpTime) {
|
if (QDateTime::currentDateTime() > giveUpTime) {
|
||||||
throw Exception("Connection to the gRPC server failed because of a timeout.", QString(), __FUNCTION__,
|
throw Exception("Connection to the gRPC server failed because of a timeout.", QString(), __FUNCTION__,
|
||||||
tailOfLatestBridgeLog());
|
tailOfLatestBridgeLog(sessionID));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -49,7 +49,8 @@ class GRPCClient : public QObject {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public: // static member functions
|
public: // static member functions
|
||||||
static void removeServiceConfigFile(QString const &configDir); ///< Delete the service config file.
|
static void removeServiceConfigFile(QString const &configDir); ///< Delete the service config file.
|
||||||
static GRPCConfig waitAndRetrieveServiceConfig(QString const &configDir, qint64 timeoutMs, class ProcessMonitor *serverProcess); ///< Wait and retrieve the service configuration.
|
static GRPCConfig waitAndRetrieveServiceConfig(QString const &sessionID, QString const &configDir, qint64 timeoutMs,
|
||||||
|
class ProcessMonitor *serverProcess); ///< Wait and retrieve the service configuration.
|
||||||
|
|
||||||
public: // member functions.
|
public: // member functions.
|
||||||
GRPCClient() = default; ///< Default constructor.
|
GRPCClient() = default; ///< Default constructor.
|
||||||
@ -59,7 +60,7 @@ public: // member functions.
|
|||||||
GRPCClient &operator=(GRPCClient const &) = delete; ///< Disabled assignment operator.
|
GRPCClient &operator=(GRPCClient const &) = delete; ///< Disabled assignment operator.
|
||||||
GRPCClient &operator=(GRPCClient &&) = delete; ///< Disabled move assignment operator.
|
GRPCClient &operator=(GRPCClient &&) = delete; ///< Disabled move assignment operator.
|
||||||
void setLog(Log *log); ///< Set the log for the client.
|
void setLog(Log *log); ///< Set the log for the client.
|
||||||
void connectToServer(QString const &configDir, GRPCConfig const &config, class ProcessMonitor *serverProcess); ///< Establish connection to the gRPC server.
|
void connectToServer(QString const &sessionID, QString const &configDir, GRPCConfig const &config, class ProcessMonitor *serverProcess); ///< Establish connection to the gRPC server.
|
||||||
bool isConnected() const; ///< Check whether the gRPC client is connected to the server.
|
bool isConnected() const; ///< Check whether the gRPC client is connected to the server.
|
||||||
|
|
||||||
grpc::Status checkTokens(QString const &clientConfigPath, QString &outReturnedClientToken); ///< Performs a token check.
|
grpc::Status checkTokens(QString const &clientConfigPath, QString &outReturnedClientToken); ///< Performs a token check.
|
||||||
|
|||||||
@ -35,34 +35,29 @@ QString userLogsDir() {
|
|||||||
|
|
||||||
//****************************************************************************************************************************************************
|
//****************************************************************************************************************************************************
|
||||||
/// \brief Return the path of the latest bridge log.
|
/// \brief Return the path of the latest bridge log.
|
||||||
|
///
|
||||||
|
/// \param[in] sessionID The sessionID.
|
||||||
/// \return The path of the latest bridge log file.
|
/// \return The path of the latest bridge log file.
|
||||||
/// \return An empty string if no bridge log file was found.
|
/// \return An empty string if no bridge log file was found.
|
||||||
//****************************************************************************************************************************************************
|
//****************************************************************************************************************************************************
|
||||||
QString latestBridgeLogPath() {
|
QString latestBridgeLogPath(QString const &sessionID) {
|
||||||
QDir const logsDir(userLogsDir());
|
QDir const logsDir(userLogsDir());
|
||||||
if (logsDir.isEmpty()) {
|
if (logsDir.isEmpty()) {
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
QFileInfoList files = logsDir.entryInfoList({ "v*.log" }, QDir::Files); // could do sorting, but only by last modification time. we want to sort by creation time.
|
QFileInfoList const files = logsDir.entryInfoList({ sessionID + "_bri_*.log" }, QDir::Files, QDir::Name);
|
||||||
if (files.isEmpty()) {
|
return files.isEmpty() ? QString() : files.back().absoluteFilePath();
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::sort(files.begin(), files.end(), [](QFileInfo const &lhs, QFileInfo const &rhs) -> bool {
|
|
||||||
return lhs.birthTime() < rhs.birthTime();
|
|
||||||
});
|
|
||||||
return files.back().absoluteFilePath();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//****************************************************************************************************************************************************
|
//****************************************************************************************************************************************************
|
||||||
/// Return the maxSize last bytes of the latest bridge log.
|
/// Return the maxSize last bytes of the latest bridge log.
|
||||||
//****************************************************************************************************************************************************
|
//****************************************************************************************************************************************************
|
||||||
QByteArray tailOfLatestBridgeLog() {
|
QByteArray tailOfLatestBridgeLog(QString const &sessionID) {
|
||||||
QString path = latestBridgeLogPath();
|
QString path = latestBridgeLogPath(sessionID);
|
||||||
if (path.isEmpty()) {
|
if (path.isEmpty()) {
|
||||||
return QByteArray();
|
return QString("We could not find a bridge log file for the current session.").toLocal8Bit();
|
||||||
}
|
}
|
||||||
|
|
||||||
QFile file(path);
|
QFile file(path);
|
||||||
|
|||||||
@ -24,7 +24,7 @@ namespace bridgepp {
|
|||||||
|
|
||||||
|
|
||||||
QString userLogsDir(); ///< Return the path of the user logs dir.
|
QString userLogsDir(); ///< Return the path of the user logs dir.
|
||||||
QByteArray tailOfLatestBridgeLog(); ///< Return the last bytes of the last bridge log.
|
QByteArray tailOfLatestBridgeLog(QString const &sessionID); ///< Return the last bytes of the last bridge log.
|
||||||
|
|
||||||
|
|
||||||
} // namespace bridgepp
|
} // namespace bridgepp
|
||||||
|
|||||||
Reference in New Issue
Block a user