diff --git a/internal/frontend/bridge-gui/bridge-gui/AppController.cpp b/internal/frontend/bridge-gui/bridge-gui/AppController.cpp index 6b69b4d1..c745b784 100644 --- a/internal/frontend/bridge-gui/bridge-gui/AppController.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/AppController.cpp @@ -76,10 +76,10 @@ ProcessMonitor *AppController::bridgeMonitor() const { //**************************************************************************************************************************************************** void AppController::onFatalError(QString const &function, QString const &message) { QString const fullMessage = QString("%1(): %2").arg(function, message); - reportSentryException(SENTRY_LEVEL_ERROR, "AppController got notified of a fatal error", "Exception", fullMessage.toLocal8Bit()); + auto uuid = reportSentryException(SENTRY_LEVEL_ERROR, "AppController got notified of a fatal error", "Exception", fullMessage.toLocal8Bit()); QMessageBox::critical(nullptr, tr("Error"), message); restart(true); - log().fatal(fullMessage); + log().fatal(QString("reportID: %1 Captured exception: %2").arg(QByteArray(uuid.bytes, 16).toHex()).arg(fullMessage)); qApp->exit(EXIT_FAILURE); } diff --git a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp index 7c26a756..6dafef9f 100644 --- a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp @@ -16,19 +16,38 @@ // along with Proton Mail Bridge. If not, see . #include "SentryUtils.h" +#include "Version.h" +#include +#include +#include +#include +#include static constexpr const char *LoggerName = "bridge-gui"; +QByteArray getProtectedHostname() { + QByteArray hostname = QCryptographicHash::hash(QSysInfo::machineHostName().toUtf8(), QCryptographicHash::Sha256); + return hostname.toHex(); +} -void reportSentryEvent(sentry_level_t level, const char *message) { +void setSentryReportScope() { + sentry_set_tag("OS", bridgepp::goos().toUtf8()); + sentry_set_tag("Client", PROJECT_FULL_NAME); + sentry_set_tag("Version", PROJECT_VER); + sentry_set_tag("UserAgent", QString("/ (%1)").arg(bridgepp::goos()).toUtf8()); + sentry_set_tag("HostArch", QSysInfo::currentCpuArchitecture().toUtf8()); + sentry_set_tag("server_name", getProtectedHostname()); +} + +sentry_uuid_t reportSentryEvent(sentry_level_t level, const char *message) { auto event = sentry_value_new_message_event(level, LoggerName, message); - sentry_capture_event(event); + return sentry_capture_event(event); } -void reportSentryException(sentry_level_t level, const char *message, const char *exceptionType, const char *exception) { +sentry_uuid_t reportSentryException(sentry_level_t level, const char *message, const char *exceptionType, const char *exception) { auto event = sentry_value_new_message_event(level, LoggerName, message); sentry_event_add_exception(event, sentry_value_new_exception(exceptionType, exception)); - sentry_capture_event(event); + return sentry_capture_event(event); } diff --git a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h index dfc0ffa9..14ed3824 100644 --- a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h +++ b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h @@ -21,8 +21,8 @@ #include - -void reportSentryEvent(sentry_level_t level, const char *message); -void reportSentryException(sentry_level_t level, const char *message, const char *exceptionType, const char *exception); +void setSentryReportScope(); +sentry_uuid_t reportSentryEvent(sentry_level_t level, const char *message); +sentry_uuid_t reportSentryException(sentry_level_t level, const char *message, const char *exceptionType, const char *exception); #endif //BRIDGE_GUI_SENTRYUTILS_H diff --git a/internal/frontend/bridge-gui/bridge-gui/build.ps1 b/internal/frontend/bridge-gui/bridge-gui/build.ps1 index 16793360..20bd2f49 100644 --- a/internal/frontend/bridge-gui/bridge-gui/build.ps1 +++ b/internal/frontend/bridge-gui/bridge-gui/build.ps1 @@ -75,6 +75,7 @@ function check_exit() { Write-host "Running build for version $bridgeVersion - $buildConfig in $buildDir" +$REVISION_HASH = git rev-parse --short=10 HEAD git submodule update --init --recursive $vcpkgRoot . $vcpkgBootstrap -disableMetrics . $vcpkgExe install sentry-native:x64-windows grpc:x64-windows --clean-after-build @@ -82,6 +83,7 @@ git submodule update --init --recursive $vcpkgRoot . $cmakeExe -G "Visual Studio 17 2022" -DCMAKE_BUILD_TYPE="$buildConfig" ` -DBRIDGE_APP_FULL_NAME="$bridgeFullName" ` -DBRIDGE_VENDOR="$bridgeVendor" ` + -DBRIDGE_REVISION=$REVISION_HASH ` -DBRIDGE_APP_VERSION="$bridgeVersion" ` -S . -B $buildDir diff --git a/internal/frontend/bridge-gui/bridge-gui/build.sh b/internal/frontend/bridge-gui/bridge-gui/build.sh index bcd84158..c47663d5 100755 --- a/internal/frontend/bridge-gui/bridge-gui/build.sh +++ b/internal/frontend/bridge-gui/bridge-gui/build.sh @@ -55,7 +55,7 @@ BRIDGE_VENDOR=${BRIDGE_VENDOR:-"Proton AG"} BUILD_CONFIG=${BRIDGE_GUI_BUILD_CONFIG:-Debug} BUILD_DIR=$(echo "./cmake-build-${BUILD_CONFIG}" | tr '[:upper:]' '[:lower:]') VCPKG_ROOT="${BRIDGE_REPO_ROOT}/extern/vcpkg" - +BRIDGE_REVISION=$(git rev-parse --short=10 HEAD) git submodule update --init --recursive ${VCPKG_ROOT} check_exit "Failed to initialize vcpkg as a submodule." @@ -93,6 +93,7 @@ cmake \ -DCMAKE_BUILD_TYPE="${BUILD_CONFIG}" \ -DBRIDGE_APP_FULL_NAME="${BRIDGE_APP_FULL_NAME}" \ -DBRIDGE_VENDOR="${BRIDGE_VENDOR}" \ + -DBRIDGE_REVISION="${BRIDGE_REVISION}" \ -DBRIDGE_APP_VERSION="${BRIDGE_APP_VERSION}" "${BRIDGE_CMAKE_MACOS_OPTS}" \ -G Ninja \ -S . \ diff --git a/internal/frontend/bridge-gui/bridge-gui/main.cpp b/internal/frontend/bridge-gui/bridge-gui/main.cpp index 47a75a28..7e2f89c7 100644 --- a/internal/frontend/bridge-gui/bridge-gui/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/main.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -238,7 +239,8 @@ void focusOtherInstance() { } catch (Exception const &e) { app().log().error(e.qwhat()); - reportSentryException(SENTRY_LEVEL_ERROR, "Exception occurred during focusOtherInstance()", "Exception", e.what()); + auto uuid = reportSentryException(SENTRY_LEVEL_ERROR, "Exception occurred during focusOtherInstance()", "Exception", e.what()); + app().log().fatal(QString("reportID: %1 Captured exception: %2").arg(QByteArray(uuid.bytes, 16).toHex()).arg(e.qwhat())); } } @@ -296,13 +298,13 @@ int main(int argc, char *argv[]) { const QString sentryCachePath = sentryCacheDir(); sentry_options_set_database_path(sentryOptions, sentryCachePath.toStdString().c_str()); } - sentry_options_set_release(sentryOptions, SentryProductID); + sentry_options_set_release(sentryOptions, QByteArray(PROJECT_REVISION).toHex()); // Enable this for debugging sentry. // sentry_options_set_debug(sentryOptions, 1); if (sentry_init(sentryOptions) != 0) { std::cerr << "Failed to initialize sentry" << std::endl; } - + setSentryReportScope(); auto sentryClose = qScopeGuard([] { sentry_close(); }); // The application instance is needed to display system message boxes. As we may have to do it in the exception handler, @@ -426,9 +428,9 @@ int main(int argc, char *argv[]) { return result; } catch (Exception const &e) { - reportSentryException(SENTRY_LEVEL_ERROR, "Exception occurred during main", "Exception", e.what()); + auto uuid = reportSentryException(SENTRY_LEVEL_ERROR, "Exception occurred during main", "Exception", e.what()); QMessageBox::critical(nullptr, "Error", e.qwhat()); - QTextStream(stderr) << e.qwhat() << "\n"; + QTextStream(stderr) << "reportID: " << QByteArray(uuid.bytes, 16).toHex() << "Captured exception :" << e.qwhat() << "\n"; return EXIT_FAILURE; } } diff --git a/internal/sentry/reporter.go b/internal/sentry/reporter.go index c8c54ef8..f9697f00 100644 --- a/internal/sentry/reporter.go +++ b/internal/sentry/reporter.go @@ -18,6 +18,7 @@ package sentry import ( + "crypto/sha256" "errors" "fmt" "log" @@ -62,12 +63,21 @@ type Reporter struct { appVersion string identifier Identifier hostArch string + serverName string } type Identifier interface { GetUserAgent() string } +func getProtectedHostname() string { + hostname, err := os.Hostname() + if err != nil { + return "Unknown" + } + return fmt.Sprintf("%x", sha256.Sum256([]byte(hostname))) +} + // NewReporter creates new sentry reporter with appName and appVersion to report. func NewReporter(appName, appVersion string, identifier Identifier) *Reporter { return &Reporter{ @@ -75,6 +85,7 @@ func NewReporter(appName, appVersion string, identifier Identifier) *Reporter { appVersion: appVersion, identifier: identifier, hostArch: getHostArch(), + serverName: getProtectedHostname(), } } @@ -126,11 +137,12 @@ func (r *Reporter) scopedReport(context map[string]interface{}, doReport func()) } tags := map[string]string{ - "OS": runtime.GOOS, - "Client": r.appName, - "Version": r.appVersion, - "UserAgent": r.identifier.GetUserAgent(), - "HostArch": r.hostArch, + "OS": runtime.GOOS, + "Client": r.appName, + "Version": r.appVersion, + "UserAgent": r.identifier.GetUserAgent(), + "HostArch": r.hostArch, + "server_name": r.serverName, } sentry.WithScope(func(scope *sentry.Scope) {