diff --git a/.github/workflows/cmake_build.yml b/.github/workflows/cmake_build.yml index 29f359e3b..1e39a0ecc 100644 --- a/.github/workflows/cmake_build.yml +++ b/.github/workflows/cmake_build.yml @@ -81,9 +81,6 @@ jobs: - name: Configure env: # Error reporing - SENTRY_DSN_KEY: ${{ secrets.SENTRY_DSN_KEY }} - SENTRY_HOST: ${{ secrets.SENTRY_HOST }} - SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} CRASH_REPORT_URL: ${{ secrets.CRASH_REPORT_URL }} # Apple code signing APPLE_CODESIGN_IDENTITY: ${{ secrets.APPLE_CODESIGN_IDENTITY }} @@ -96,18 +93,6 @@ jobs: run: | exec bash "scripts/ci/build.sh" - - name: Upload debug symbols - if: startsWith(github.ref, 'refs/heads/release-') - env: - SENTRY_HOST: ${{ secrets.SENTRY_HOST }} - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - SENTRY_ORG_SLUG: ${{ secrets.SENTRY_ORG_SLUG }} - SENTRY_PROJECT_SLUG: ${{ secrets.SENTRY_PROJECT_SLUG }} - #this is required to run sentry's get-cli script on platforms where 'sudo' is not available - INSTALL_DIR: ${{ github.workspace }} - run: | - exec bash "scripts/ci/upload_debug_symbols.sh" - - name: Install run: | exec bash "scripts/ci/install.sh" diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b8ac7605..9fe3e77a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,19 +170,8 @@ include( CMakePushCheckState ) include( GNUInstallDirs ) include( TestBigEndian ) -set_from_env(SENTRY_DSN_KEY) -set_from_env(SENTRY_HOST) -set_from_env(SENTRY_PROJECT) set_from_env(CRASH_REPORT_URL) -cmake_dependent_option( - ${_OPT}has_sentry_reporting - "Build support for sending errors to Sentry" - On - "${_OPT}has_networking;DEFINED SENTRY_DSN_KEY;DEFINED SENTRY_HOST;DEFINED SENTRY_PROJECT" - Off -) - cmake_dependent_option( ${_OPT}has_crashreports "Enables crash reporting for Audacity" diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index 591c14d0f..046fae2d9 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -9,15 +9,6 @@ set( LIBRARIES lib-uuid ) -if ( ${_OPT}has_networking ) - list( APPEND LIBRARIES lib-network-manager) -endif() - -# This library depends on lib-network-manager -# If Sentry reporting is disabled, an INTERFACE library -# will be defined -list( APPEND LIBRARIES lib-sentry-reporting) - foreach( LIBRARY ${LIBRARIES} ) add_subdirectory( "${LIBRARY}" ) endforeach() diff --git a/libraries/lib-sentry-reporting/AnonymizedMessage.cpp b/libraries/lib-sentry-reporting/AnonymizedMessage.cpp deleted file mode 100644 index 9edd603b0..000000000 --- a/libraries/lib-sentry-reporting/AnonymizedMessage.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/*!******************************************************************** - - Audacity: A Digital Audio Editor - - @file AnonymizedMessage.cpp - @brief Define a class to store anonymized messages. - - Dmitry Vedenko - **********************************************************************/ - -#include "AnonymizedMessage.h" - -#include - -#include "CodeConversions.h" - -namespace audacity -{ -namespace sentry -{ - -AnonymizedMessage::AnonymizedMessage(std::string message) - : mMessage(std::move(message)) -{ - CleanupPaths(); -} - -AnonymizedMessage::AnonymizedMessage(const std::wstring& message) - : AnonymizedMessage(ToUTF8(message)) -{ -} - -AnonymizedMessage::AnonymizedMessage(const wxString& message) - : AnonymizedMessage(ToUTF8(message)) -{ -} - -AnonymizedMessage::AnonymizedMessage(const char* message) - : AnonymizedMessage(std::string(message)) -{ -} - -AnonymizedMessage::AnonymizedMessage(const wchar_t* message) - : AnonymizedMessage(ToUTF8(message)) -{ -} - -bool AnonymizedMessage::Empty() const noexcept -{ - return mMessage.empty(); -} - -size_t AnonymizedMessage::Length() const noexcept -{ - return mMessage.size(); -} - -const std::string& AnonymizedMessage::GetString() const noexcept -{ - return mMessage; -} - -wxString AnonymizedMessage::ToWXString() const noexcept -{ - return audacity::ToWXString(mMessage); -} - -const char* AnonymizedMessage::c_str() const noexcept -{ - return mMessage.c_str(); -} - -size_t AnonymizedMessage::length() const noexcept -{ - return mMessage.length(); -} - -void AnonymizedMessage::CleanupPaths() -{ - // Finding the path boundary in the arbitrary text is a hard task. - // We assume that spaces cannot be a part of the path. - // In the worst case - we will get - static const std::regex re( - R"(\b(?:(?:[a-zA-Z]:)?[\\/]?)?(?:[^<>:"/|\\/?\s*]+[\\/]+)*(?:[^<>:"/|\\/?*\s]+\.\w+)?)"); - - mMessage = std::regex_replace( - mMessage, re, "", std::regex_constants::match_not_null); -} - -} // namespace sentry -} // namespace audacity diff --git a/libraries/lib-sentry-reporting/AnonymizedMessage.h b/libraries/lib-sentry-reporting/AnonymizedMessage.h deleted file mode 100644 index bc83b9468..000000000 --- a/libraries/lib-sentry-reporting/AnonymizedMessage.h +++ /dev/null @@ -1,70 +0,0 @@ -/*!******************************************************************** - - Audacity: A Digital Audio Editor - - @file AnonymizedMessage.h - @brief Declare a class to store anonymized messages. - - Dmitry Vedenko - **********************************************************************/ - -#include -#include - -#pragma once - -namespace audacity -{ -namespace sentry -{ -//! A class, that stores anonymized message. -/*! - Input message is anonymized by looking for path-like patterns. - Messages are stored in UTF8 format. -*/ -class SENTRY_REPORTING_API AnonymizedMessage final -{ -public: - //! Creates an empty message - AnonymizedMessage() = default; - - AnonymizedMessage(const AnonymizedMessage&) = default; - AnonymizedMessage(AnonymizedMessage&&) = default; - - AnonymizedMessage& operator=(const AnonymizedMessage&) = default; - AnonymizedMessage& operator=(AnonymizedMessage&&) = default; - - //! Creates a message from std::string - AnonymizedMessage(std::string message); - //! Creates a message from std::wstring - AnonymizedMessage(const std::wstring& message); - //! Creates a message from wxString - AnonymizedMessage(const wxString& message); - //! Creates a message from const char* - AnonymizedMessage(const char* message); - //! Creates a message from const wchar_t* - AnonymizedMessage(const wchar_t* message); - - //! Checks, if the message is empty - bool Empty() const noexcept; - //! Returns the length of the message - size_t Length() const noexcept; - - //! Returns the UTF8 representation of the message - const std::string& GetString() const noexcept; - //! Convert the message to wxString - wxString ToWXString() const noexcept; - - // Imitate std::string interface - //! Checks, if the message is empty - const char* c_str() const noexcept; - //! Returns the length of the message - size_t length() const noexcept; -private: - void CleanupPaths(); - - std::string mMessage; -}; - -} // namespace sentry -} // namespace audacity diff --git a/libraries/lib-sentry-reporting/CMakeLists.txt b/libraries/lib-sentry-reporting/CMakeLists.txt deleted file mode 100644 index 4d53b01f3..000000000 --- a/libraries/lib-sentry-reporting/CMakeLists.txt +++ /dev/null @@ -1,48 +0,0 @@ -#[[ -A library, that allows sending error reports to a Sentry server -using Exception and Message interfaces. -]]# - -set( TARGET lib-sentry-reporting ) -set( TARGET_ROOT ${CMAKE_CURRENT_SOURCE_DIR} ) - -def_vars() - -if(${_OPT}has_sentry_reporting) - set( SOURCES - SentryHelper.h - - AnonymizedMessage.h - AnonymizedMessage.cpp - - SentryReport.h - SentryReport.cpp - - SentryRequestBuilder.h - SentryRequestBuilder.cpp - ) - - - set ( LIBRARIES PRIVATE - lib-network-manager # Required for the networking - lib-string-utils # ToUtf8 - lib-uuid # UUIDs are required as an event identifier. - RapidJSON::RapidJSON # Protocol is JSON based - wxwidgets::base # Required to retreive the OS information - ) - - set ( DEFINES - INTERFACE - HAS_SENTRY_REPORTING=1 - PRIVATE - # The variables below will be used to construct Sentry URL: - # https://${SENTRY_DSN_KEY}@${SENTRY_HOST}/api/${SENTRY_PROJECT}/store - SENTRY_DSN_KEY="${SENTRY_DSN_KEY}" - SENTRY_HOST="${SENTRY_HOST}" - SENTRY_PROJECT="${SENTRY_PROJECT}" - ) - - audacity_library( ${TARGET} "${SOURCES}" "${LIBRARIES}" "${DEFINES}" "" ) -else() - audacity_header_only_library( ${TARGET} "SentryHelper.h" "" "" "" ) -endif() \ No newline at end of file diff --git a/libraries/lib-sentry-reporting/SentryHelper.h b/libraries/lib-sentry-reporting/SentryHelper.h deleted file mode 100644 index 0184bcf10..000000000 --- a/libraries/lib-sentry-reporting/SentryHelper.h +++ /dev/null @@ -1,25 +0,0 @@ -/********************************************************************** - - Audacity: A Digital Audio Editor - - SentryHelper.h - - Defines a macro ADD_EXCEPTION_CONTEXT, that is a no op if Sentry reporting is disabled. - - Dmitry Vedenko - -**********************************************************************/ - -#ifndef __AUDACITY_SENTRY__ -#define __AUDACITY_SENTRY__ - -#ifdef HAS_SENTRY_REPORTING -# include "SentryReport.h" - -# define ADD_EXCEPTION_CONTEXT(name, value) audacity::sentry::AddExceptionContext(name, value) -#else -# define ADD_EXCEPTION_CONTEXT(name, value) -#endif // HAS_SENTRY_REPORTING - - -#endif /* __AUDACITY_SENTRY__ */ diff --git a/libraries/lib-sentry-reporting/SentryReport.cpp b/libraries/lib-sentry-reporting/SentryReport.cpp deleted file mode 100644 index fb045eca9..000000000 --- a/libraries/lib-sentry-reporting/SentryReport.cpp +++ /dev/null @@ -1,428 +0,0 @@ -/*!******************************************************************** - - Audacity: A Digital Audio Editor - - @file SentryReport.cpp - @brief Define a class to report errors to Sentry. - - Dmitry Vedenko - **********************************************************************/ - -#include "SentryReport.h" - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include "CodeConversions.h" -#include "Uuid.h" - -#include "IResponse.h" -#include "NetworkManager.h" - -#include "SentryRequestBuilder.h" - -namespace audacity -{ -namespace sentry -{ -namespace -{ - -//! Helper class to store additional details about the exception -/*! This small class is a thread safe store for the information - we want to add to the exception before the exception occurs. - For example, we may log SQLite3 return codes here, as otherwise - they wont be available when everything fails -*/ -class ExceptionContext final -{ -public: - //! Adds a new item to the exception context - void Add(std::string parameterName, AnonymizedMessage parameterValue) - { - std::lock_guard lock(mDataMutex); - mData.emplace_back(std::move(parameterName), std::move(parameterValue)); - } - - //! Return the current context and reset it - std::vector MoveParameters() - { - std::lock_guard lock(mDataMutex); - - std::vector emptyVector; - - std::swap(mData, emptyVector); - - return emptyVector; - } - - //! Get an instance of the ExceptionContext - static ExceptionContext& Get() - { - static ExceptionContext instance; - return instance; - } - -private: - ExceptionContext() = default; - - std::mutex mDataMutex; - std::vector mData; -}; - -//! Append the data about the operating system to the JSON document -void AddOSContext( - rapidjson::Value& root, rapidjson::Document::AllocatorType& allocator) -{ - rapidjson::Value osContext(rapidjson::kObjectType); - - const wxPlatformInfo platformInfo = wxPlatformInfo::Get(); - - const std::string osName = - ToUTF8(platformInfo.GetOperatingSystemFamilyName()); - - osContext.AddMember("type", rapidjson::Value("os", allocator), allocator); - - osContext.AddMember( - "name", rapidjson::Value(osName.c_str(), osName.length(), allocator), - allocator); - - const std::string osVersion = - std::to_string(platformInfo.GetOSMajorVersion()) + "." + - std::to_string(platformInfo.GetOSMinorVersion()) + "." + - std::to_string(platformInfo.GetOSMicroVersion()); - - osContext.AddMember( - "version", - rapidjson::Value(osVersion.c_str(), osVersion.length(), allocator), - allocator); - - root.AddMember("os", std::move(osContext), allocator); -} - -//! Create the minimal required Sentry JSON document -rapidjson::Document CreateSentryDocument() -{ - using namespace std::chrono; - rapidjson::Document document; - - document.SetObject(); - - document.AddMember( - "timestamp", - rapidjson::Value( - duration_cast(system_clock::now().time_since_epoch()) - .count()), - document.GetAllocator()); - - std::string eventId = Uuid::Generate().ToHexString(); - - document.AddMember( - "event_id", - rapidjson::Value( - eventId.c_str(), eventId.length(), document.GetAllocator()), - document.GetAllocator()); - - constexpr char platform[] = "native"; - - document.AddMember( - "platform", - rapidjson::Value(platform, sizeof(platform) - 1, document.GetAllocator()), - document.GetAllocator()); - - document["platform"].SetString( - platform, sizeof(platform) - 1, document.GetAllocator()); - - const std::string release = std::string("audacity@") + - std::to_string(AUDACITY_VERSION) + "." + - std::to_string(AUDACITY_RELEASE) + "." + - std::to_string(AUDACITY_REVISION); - - document.AddMember( - "release", - rapidjson::Value( - release.c_str(), release.length(), document.GetAllocator()), - document.GetAllocator()); - - rapidjson::Value contexts = rapidjson::Value(rapidjson::kObjectType); - - AddOSContext(contexts, document.GetAllocator()); - - document.AddMember("contexts", contexts, document.GetAllocator()); - - return document; -} - -//! Append the ExceptionData to the Exception JSON object -void AddExceptionDataToJson( - rapidjson::Value& value, rapidjson::Document::AllocatorType& allocator, - const ExceptionData& data) -{ - value.AddMember( - rapidjson::Value(data.first.c_str(), data.first.length(), allocator), - rapidjson::Value(data.second.c_str(), data.second.length(), allocator), - allocator); -} - -//! Serialize the Exception to JSON -void SerializeException( - const Exception& exception, rapidjson::Value& root, - rapidjson::Document::AllocatorType& allocator) -{ - root.AddMember( - "type", - rapidjson::Value( - exception.Type.c_str(), exception.Type.length(), allocator), - allocator); - - root.AddMember( - "value", - rapidjson::Value( - exception.Value.c_str(), exception.Value.length(), allocator), - allocator); - - rapidjson::Value mechanismObject(rapidjson::kObjectType); - - mechanismObject.AddMember( - "type", rapidjson::Value("runtime_error", allocator), allocator); - - mechanismObject.AddMember( - "handled", false, allocator); - - auto contextData = ExceptionContext::Get().MoveParameters(); - - if (!exception.Data.empty() || !contextData.empty()) - { - rapidjson::Value dataObject(rapidjson::kObjectType); - - for (const auto& data : contextData) - AddExceptionDataToJson(dataObject, allocator, data); - - for (const auto& data : exception.Data) - AddExceptionDataToJson(dataObject, allocator, data); - - mechanismObject.AddMember("data", std::move(dataObject), allocator); - } - - root.AddMember("mechanism", std::move(mechanismObject), allocator); -} - -} // namespace - -Exception Exception::Create(std::string type, AnonymizedMessage value) -{ - std::replace_if(type.begin(), type.end(), [](char c) { - return std::isspace(c) != 0; - }, '_'); - - return { std::move(type), std::move(value) }; -} - -Exception Exception::Create(AnonymizedMessage value) -{ - return { "runtime_error", std::move(value) }; -} - -Exception& Exception::AddData(std::string key, AnonymizedMessage value) -{ - Data.emplace_back(std::move(key), std::move(value)); - return *this; -} - -Message Message::Create(AnonymizedMessage message) -{ - return { std::move(message) }; -} - -Message& Message::AddParam(AnonymizedMessage value) -{ - Params.emplace_back(std::move(value)); - return *this; -} - -void AddExceptionContext( - std::string parameterName, AnonymizedMessage parameterValue) -{ - ExceptionContext::Get().Add(std::move (parameterName), std::move (parameterValue)); -} - -class Report::ReportImpl -{ -public: - explicit ReportImpl(const Exception& exception); - explicit ReportImpl(const Message& message); - - void AddUserComment(const std::string& message); - - std::string ToString(bool pretty) const; - - void Send(CompletionHandler completionHandler) const; - -private: - rapidjson::Document mDocument; -}; - - -Report::ReportImpl::ReportImpl(const Exception& exception) - : mDocument(CreateSentryDocument()) -{ - rapidjson::Value exceptionObject(rapidjson::kObjectType); - rapidjson::Value valuesArray(rapidjson::kArrayType); - rapidjson::Value valueObject(rapidjson::kObjectType); - - SerializeException(exception, valueObject, mDocument.GetAllocator()); - - valuesArray.PushBack(std::move(valueObject), mDocument.GetAllocator()); - - exceptionObject.AddMember( - "values", std::move(valuesArray), mDocument.GetAllocator()); - - mDocument.AddMember( - "exception", std::move(exceptionObject), mDocument.GetAllocator()); -} - -Report::ReportImpl::ReportImpl(const Message& message) - : mDocument(CreateSentryDocument()) -{ - rapidjson::Value messageObject(rapidjson::kObjectType); - - messageObject.AddMember( - "message", - rapidjson::Value( - message.Value.c_str(), message.Value.length(), - mDocument.GetAllocator()), - mDocument.GetAllocator()); - - if (!message.Params.empty()) - { - rapidjson::Value paramsArray(rapidjson::kArrayType); - - for (const AnonymizedMessage& param : message.Params) - { - paramsArray.PushBack( - rapidjson::Value( - param.c_str(), param.length(), mDocument.GetAllocator()), - mDocument.GetAllocator()); - } - - messageObject.AddMember( - "params", std::move(paramsArray), mDocument.GetAllocator()); - } - - mDocument.AddMember( - "message", std::move(messageObject), mDocument.GetAllocator()); -} - -void Report::ReportImpl::AddUserComment(const std::string& message) -{ - // We only allow adding comment to exceptions now - if (!mDocument.HasMember("exception") || message.empty()) - return; - - rapidjson::Value& topException = mDocument["exception"]["values"][0]; - - if (!topException.IsObject()) - return; - - rapidjson::Value& mechanism = topException["mechanism"]; - - // Create a data object if it still does not exist - if (!mechanism.HasMember("data")) - { - mechanism.AddMember( - "data", rapidjson::Value(rapidjson::kObjectType), - mDocument.GetAllocator()); - } - - // Add a comment itself - mechanism["data"].AddMember( - "user_comment", - rapidjson::Value( - message.data(), message.length(), mDocument.GetAllocator()), - mDocument.GetAllocator()); -} - - -void Report::ReportImpl::Send(CompletionHandler completionHandler) const -{ - const std::string serializedDocument = ToString(false); - - network_manager::Request request = - SentryRequestBuilder::Get().CreateRequest(); - - auto response = network_manager::NetworkManager::GetInstance().doPost( - request, serializedDocument.data(), serializedDocument.size()); - - response->setRequestFinishedCallback( - [response, handler = std::move(completionHandler)](network_manager::IResponse*) { - const std::string responseData = response->readAll(); - - wxLogDebug(responseData.c_str()); - - if (handler) - handler(response->getHTTPCode(), responseData); - }); -} - -std::string Report::ReportImpl::ToString(bool pretty) const -{ - rapidjson::StringBuffer buffer; - - if (pretty) - { - rapidjson::PrettyWriter writer(buffer); - mDocument.Accept(writer); - } - else - { - rapidjson::Writer writer(buffer); - mDocument.Accept(writer); - } - - return std::string(buffer.GetString()); -} - -Report::~Report() -{ -} - -Report::Report(const Exception& exception) - : mImpl(std::make_unique(exception)) -{ -} - -Report::Report(const Message& message) - : mImpl(std::make_unique(message)) -{ -} - -void Report::AddUserComment(const std::string& comment) -{ - mImpl->AddUserComment(comment); -} - -std::string Report::GetReportPreview() const -{ - return mImpl->ToString(true); -} - -void Report::Send(CompletionHandler completionHandler) const -{ - mImpl->Send(std::move (completionHandler)); -} - - -} // namespace sentry -} // namespace audacity diff --git a/libraries/lib-sentry-reporting/SentryReport.h b/libraries/lib-sentry-reporting/SentryReport.h deleted file mode 100644 index ce2b24338..000000000 --- a/libraries/lib-sentry-reporting/SentryReport.h +++ /dev/null @@ -1,95 +0,0 @@ -/*!******************************************************************** - - Audacity: A Digital Audio Editor - - @file SentryReport.h - @brief Declare a class to report errors to Sentry. - - Dmitry Vedenko - **********************************************************************/ - -#pragma once - -#include -#include -#include -#include -#include - -#include "AnonymizedMessage.h" - -namespace audacity -{ -namespace sentry -{ - -//! Additional payload to the exception -using ExceptionData = std::pair; - -//! A DTO for the Sentry Exception interface -struct SENTRY_REPORTING_API Exception final -{ - //! Exception type. Should not have spaces. - std::string Type; - //! Message, associated with the Exception - AnonymizedMessage Value; - //! Arbitrary payload - std::vector Data; - - //! Create a new exception - static Exception Create(std::string type, AnonymizedMessage value); - //! Create a new exception with type runtime_error - static Exception Create(AnonymizedMessage value); - //! Add a payload to the exception - Exception& AddData(std::string key, AnonymizedMessage value); -}; - -//! A DTO for the Sentry Message interface -struct SENTRY_REPORTING_API Message final -{ - //! A string, possibly with %s placeholders, containing the message - AnonymizedMessage Value; - //! Values for the placeholders - std::vector Params; - //! Create a new Message - static Message Create(AnonymizedMessage message); - //! Add a parameter to the Message - Message& AddParam(AnonymizedMessage value); -}; - -//! Saves a parameter, that will be appended to the next Exception report -SENTRY_REPORTING_API void AddExceptionContext( - std::string parameterName, AnonymizedMessage parameterValue); - -//! A report to Sentry -class SENTRY_REPORTING_API Report final -{ -public: - //! A callback, that will be called when Send completes - using CompletionHandler = std::function; - - //! Create a report from the exception and previously added exception context - explicit Report(const Exception& exception); - - //! Create a report with a single log message - explicit Report(const Message& message); - - ~Report(); - - //! Adds a user comment to the exception report - void AddUserComment(const std::string& comment); - - //! Get a pretty printed report preview - std::string GetReportPreview() const; - - //! Send the report to Sentry - void Send(CompletionHandler completionHandler) const; - -private: - class ReportImpl; - - std::unique_ptr mImpl; -}; - -} // namespace sentry -} // namespace audacity diff --git a/libraries/lib-sentry-reporting/SentryRequestBuilder.cpp b/libraries/lib-sentry-reporting/SentryRequestBuilder.cpp deleted file mode 100644 index 6bda81603..000000000 --- a/libraries/lib-sentry-reporting/SentryRequestBuilder.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/*!******************************************************************** - - Audacity: A Digital Audio Editor - - @file SentryRequestBuilder.h - @brief Define a class to generate the requests to Sentry. - - Dmitry Vedenko - **********************************************************************/ - -#include "SentryRequestBuilder.h" - -#include - -namespace audacity -{ -namespace sentry -{ - -const SentryRequestBuilder& audacity::sentry::SentryRequestBuilder::Get() -{ - static SentryRequestBuilder builder; - - return builder; -} - -network_manager::Request SentryRequestBuilder::CreateRequest() const -{ - using namespace std::chrono; - - const std::string sentryAuth = - std::string("Sentry sentry_version=7,sentry_timestamp=") + - std::to_string( - duration_cast(system_clock::now().time_since_epoch()) - .count()) + - ",sentry_client=sentry-audacity/1.0,sentry_key=" + SENTRY_DSN_KEY; - - network_manager::Request request(mUrl); - - request.setHeader("Content-Type", "application/json"); - request.setHeader("X-Sentry-Auth", sentryAuth); - - return request; -} - -SentryRequestBuilder::SentryRequestBuilder() -{ - mUrl = std::string("https://") + SENTRY_DSN_KEY + "@" + SENTRY_HOST + - "/api/" + SENTRY_PROJECT + "/store/"; -} - -} // namespace sentry -} // namespace audacity diff --git a/libraries/lib-sentry-reporting/SentryRequestBuilder.h b/libraries/lib-sentry-reporting/SentryRequestBuilder.h deleted file mode 100644 index 560010e0c..000000000 --- a/libraries/lib-sentry-reporting/SentryRequestBuilder.h +++ /dev/null @@ -1,36 +0,0 @@ -/*!******************************************************************** - - Audacity: A Digital Audio Editor - - @file SentryRequestBuilder.cpp - @brief Declare a class to generate the requests to Sentry. - - Dmitry Vedenko - **********************************************************************/ - -#pragma once - -#include - -#include "Request.h" - -namespace audacity -{ -namespace sentry -{ -// This is a private class, so it is not exported -//! A helper, that creates a correct Request to Sentry -class SentryRequestBuilder final -{ -public: - static const SentryRequestBuilder& Get(); - - network_manager::Request CreateRequest() const; - -private: - SentryRequestBuilder(); - - std::string mUrl; -}; -} // namespace sentry -} // namespace audacity diff --git a/scripts/ci/upload_debug_symbols.sh b/scripts/ci/upload_debug_symbols.sh deleted file mode 100644 index 9554cd044..000000000 --- a/scripts/ci/upload_debug_symbols.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash - -((${BASH_VERSION%%.*} >= 4)) || { echo >&2 "$0: Error: Please upgrade Bash."; exit 1; } - -set -euxo pipefail - -# download sentry-cli -# TODO: currently this script downloads binaries and install them -# each time job is started, workarounds? -curl -sL https://sentry.io/get-cli/ | bash - -SYMBOLS=$(find debug | xargs) - -${INSTALL_DIR}/sentry-cli --auth-token ${SENTRY_AUTH_TOKEN} --url ${SENTRY_HOST} upload-dif \ - --org ${SENTRY_ORG_SLUG} \ - --project ${SENTRY_PROJECT_SLUG} ${SYMBOLS} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c35143aef..284559710 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -959,10 +959,6 @@ list( APPEND SOURCES widgets/ReadOnlyText.h widgets/Ruler.cpp widgets/Ruler.h - $<$: - widgets/ErrorReportDialog.cpp - widgets/ErrorReportDialog.h - > widgets/Warning.cpp widgets/Warning.h widgets/WindowAccessible.cpp diff --git a/src/widgets/ErrorDialog.cpp b/src/widgets/ErrorDialog.cpp index a167401b4..6d9d95751 100644 --- a/src/widgets/ErrorDialog.cpp +++ b/src/widgets/ErrorDialog.cpp @@ -39,9 +39,6 @@ #include "../Prefs.h" #include "HelpSystem.h" -#ifdef HAS_SENTRY_REPORTING -# include "ErrorReportDialog.h" -#endif BEGIN_EVENT_TABLE(ErrorDialog, wxDialogWrapper) EVT_COLLAPSIBLEPANE_CHANGED( wxID_ANY, ErrorDialog::OnPane ) @@ -169,13 +166,8 @@ void ShowExceptionDialog( const TranslatableString& message, const wxString& helpPage, bool Close, const wxString& log) { -#ifndef HAS_SENTRY_REPORTING ShowErrorDialog(parent, dlogTitle, message, helpPage, Close, audacity::ToWString(log)); -#else - ShowErrorReportDialog(parent, dlogTitle, message, helpPage, - audacity::ToWString(log)); -#endif // !HAS_SENTRY_REPORTING } // unused. diff --git a/src/widgets/ErrorReportDialog.cpp b/src/widgets/ErrorReportDialog.cpp deleted file mode 100644 index d8ba15635..000000000 --- a/src/widgets/ErrorReportDialog.cpp +++ /dev/null @@ -1,221 +0,0 @@ -/********************************************************************** - - Audacity: A Digital Audio Editor - - ErrorReportDialog.cpp - - Dmitry Vedenko - -**********************************************************************/ - -#include "ErrorReportDialog.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "AllThemeResources.h" -#include "Theme.h" -#include "HelpText.h" -#include "Prefs.h" -#include "ShuttleGui.h" -#include "HelpSystem.h" - -#include "SentryReport.h" -#include "CodeConversions.h" - -constexpr int MaxUserCommentLength = 2000; - -BEGIN_EVENT_TABLE(ErrorReportDialog, wxDialogWrapper) - EVT_BUTTON(wxID_YES, ErrorReportDialog::OnSend) - EVT_BUTTON(wxID_NO, ErrorReportDialog::OnDontSend) - EVT_BUTTON(wxID_HELP, ErrorReportDialog::OnHelp) -END_EVENT_TABLE() - -ErrorReportDialog::ErrorReportDialog( - wxWindow* parent, const TranslatableString& dlogTitle, - const TranslatableString& message, const wxString& helpUrl, - const wxString& log, const bool modal) - : wxDialogWrapper( - parent, wxID_ANY, dlogTitle, wxDefaultPosition, wxDefaultSize, - wxDEFAULT_DIALOG_STYLE) - , mHelpUrl(helpUrl) - , mIsModal(modal) -{ - audacity::sentry::Exception ex = audacity::sentry::Exception::Create( - audacity::ToUTF8(dlogTitle.Debug()),message.Debug()); - - if (!log.empty()) - ex.AddData("log", log); - - mReport = std::make_unique (ex); - - ShuttleGui S(this, eIsCreating); - - const wxFont headingFont = wxFont(wxFontInfo(12).Bold()); - const wxFont textFont = wxFont(wxFontInfo(10)); - - S.SetBorder(0); - - S.StartHorizontalLay(wxEXPAND, 0); - { - S.AddSpace(40, 0); - S.StartVerticalLay(wxEXPAND, 0); - { - S.AddSpace(0, 32); - - S.StartHorizontalLay(wxEXPAND, 1); - { - S.StartVerticalLay(0); - { - wxBitmap bitmap = wxArtProvider::GetBitmap( - wxART_WARNING, wxART_MESSAGE_BOX, wxSize(24, 24)); - - S.Prop(0).AddWindow( - safenew wxStaticBitmap(S.GetParent(), -1, bitmap)); - - S.AddSpace(0, 0, 1); - } - S.EndVerticalLay(); - - S.AddSpace(10, 0); - - S.StartVerticalLay(0); - { - S.AddSpace(0, 7); - - S.Prop(1) - .AddVariableText(message, false, 0, 560) - ->SetFont(headingFont); - } - S.EndVerticalLay(); - } - S.EndHorizontalLay(); - - S.AddSpace(0, 20); - - S.AddVariableText(XO( - "Click \"Send\" to submit the report to Audacity. This information is collected anonymously.")) - ->SetFont(textFont); - - S.AddSpace(0, 20); - - S.AddVariableText(XO("Problem details"))->SetFont(textFont); - - S.AddSpace(0, 6); - - S.Style(wxTE_RICH | wxTE_READONLY | wxTE_MULTILINE | wxTE_DONTWRAP) - .MinSize(wxSize(0, 152)) - .Name(XO("Problem details")) - .AddTextBox({}, mReport->GetReportPreview(), 0); - - S.AddSpace(0, 20); - - S.AddVariableText(XO("Comments"))->SetFont(textFont); - - S.AddSpace(0, 6); - - mCommentsControl = S.Style(wxTE_MULTILINE) - .MinSize(wxSize(0, 76)) - .Name(XO("Comments")) - .AddTextBox({}, {}, 0); - - mCommentsControl->SetMaxLength(MaxUserCommentLength); - - S.AddSpace(0, 20); - - S.StartHorizontalLay(wxEXPAND); - { - if (!mHelpUrl.empty()) - { - wxBitmapButton* helpButton = - S.Id(wxID_HELP).AddBitmapButton(theTheme.Bitmap(bmpHelpIcon)); - // For screen readers - helpButton->SetToolTip(XO("Help").Translation()); - helpButton->SetLabel(XO("Help").Translation()); - } - - S.AddSpace(0, 0, 1); - - S.Id(wxID_NO).AddButton(XC("&Don't send", "crash reporter button")); - - S.AddSpace(13, 0); - - S.Id(wxID_YES).AddButton(XC("&Send", "crash reporter button")); - } - S.EndHorizontalLay(); - - S.AddSpace(0, 20); - } - S.EndVerticalLay(); - - S.AddSpace(28, 0); - } - S.EndHorizontalLay(); - - S.SetBorder(2); - - Layout(); - GetSizer()->Fit(this); - SetMinSize(GetSize()); - Center(); -} - -ErrorReportDialog::~ErrorReportDialog() -{ -} - -void ErrorReportDialog::OnSend(wxCommandEvent& event) -{ - Disable(); - - mReport->AddUserComment(audacity::ToUTF8(mCommentsControl->GetValue())); - - mReport->Send( - [this](int code, std::string body) { - CallAfter([this]() { - EndModal(true); - }); - }); -} - -void ErrorReportDialog::OnDontSend(wxCommandEvent& event) -{ - EndModal(true); -} - -void ErrorReportDialog::OnHelp(wxCommandEvent& event) -{ - if (mHelpUrl.StartsWith(wxT("innerlink:"))) - { - HelpSystem::ShowHtmlText( - this, TitleText(mHelpUrl.Mid(10)), HelpText(mHelpUrl.Mid(10)), false, - true); - return; - } - - HelpSystem::ShowHelp(this, mHelpUrl, false); -} - -void ShowErrorReportDialog( - wxWindow* parent, const TranslatableString& dlogTitle, - const TranslatableString& message, const wxString& helpPage, - const wxString& log) -{ - ErrorReportDialog dlog(parent, dlogTitle, message, helpPage, log); - - dlog.CentreOnParent(); - dlog.ShowModal(); -} diff --git a/src/widgets/ErrorReportDialog.h b/src/widgets/ErrorReportDialog.h deleted file mode 100644 index ecc2d83b3..000000000 --- a/src/widgets/ErrorReportDialog.h +++ /dev/null @@ -1,69 +0,0 @@ -/********************************************************************** - - Audacity: A Digital Audio Editor - - ErrorReportDialog.h - - Dmitry Vedenko - -**********************************************************************/ - -#ifndef __AUDACITY_SENTRYERRORDIALOG__ -#define __AUDACITY_SENTRYERRORDIALOG__ - -#include - -#include -#include - -#include "wxPanelWrapper.h" // to inherit - -namespace audacity -{ -namespace sentry -{ -class Report; -} -} - -class wxTextCtrl; - -//! A dialog, that has "Send", "Don't send" and help buttons. -/*! This dialog is used in place of error dialogs for Audacity errors - when Sentry reporting is enabled. -*/ -class ErrorReportDialog final : public wxDialogWrapper -{ -public: - ErrorReportDialog( - wxWindow* parent, const TranslatableString& dlogTitle, - const TranslatableString& message, const wxString& helpUrl, - const wxString& log, const bool modal = true); - - ~ErrorReportDialog(); - -private: - void OnSend(wxCommandEvent& event); - void OnDontSend(wxCommandEvent& event); - - void OnHelp(wxCommandEvent& event); - - std::unique_ptr mReport; - - wxString mHelpUrl; - - wxTextCtrl* mCommentsControl; - - bool mIsModal; - - DECLARE_EVENT_TABLE() -}; - -/// Displays an error dialog that allows to send the error report -AUDACITY_DLL_API -void ShowErrorReportDialog( - wxWindow* parent, const TranslatableString& dlogTitle, - const TranslatableString& message, const wxString& helpPage = {}, - const wxString& log = {}); - -#endif // __AUDACITY_SENTRYERRORDIALOG__