1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-14 23:30:23 +02:00

💩 Remove Sentry Reporting

This commit is contained in:
Cookie Engineer 2021-07-04 10:19:04 +02:00
parent 29a1ae6faa
commit bbf352d36d
No known key found for this signature in database
GPG Key ID: 340F6A4848C5F849
16 changed files with 0 additions and 1199 deletions

View File

@ -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"

View File

@ -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"

View File

@ -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()

View File

@ -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 <regex>
#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 <path> <path>
static const std::regex re(
R"(\b(?:(?:[a-zA-Z]:)?[\\/]?)?(?:[^<>:"/|\\/?\s*]+[\\/]+)*(?:[^<>:"/|\\/?*\s]+\.\w+)?)");
mMessage = std::regex_replace(
mMessage, re, "<path>", std::regex_constants::match_not_null);
}
} // namespace sentry
} // namespace audacity

View File

@ -1,70 +0,0 @@
/*!********************************************************************
Audacity: A Digital Audio Editor
@file AnonymizedMessage.h
@brief Declare a class to store anonymized messages.
Dmitry Vedenko
**********************************************************************/
#include <string>
#include <wx/string.h>
#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

View File

@ -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()

View File

@ -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__ */

View File

@ -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 <chrono>
#include <cstring>
#include <mutex>
#include <algorithm>
#include <cctype>
#include <regex>
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/prettywriter.h>
#include <wx/platinfo.h>
#include <wx/log.h>
#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<std::mutex> lock(mDataMutex);
mData.emplace_back(std::move(parameterName), std::move(parameterValue));
}
//! Return the current context and reset it
std::vector<ExceptionData> MoveParameters()
{
std::lock_guard<std::mutex> lock(mDataMutex);
std::vector<ExceptionData> 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<ExceptionData> 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<seconds>(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<std::string>();
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<rapidjson::StringBuffer> writer(buffer);
mDocument.Accept(writer);
}
else
{
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
mDocument.Accept(writer);
}
return std::string(buffer.GetString());
}
Report::~Report()
{
}
Report::Report(const Exception& exception)
: mImpl(std::make_unique<ReportImpl>(exception))
{
}
Report::Report(const Message& message)
: mImpl(std::make_unique<ReportImpl>(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

View File

@ -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 <string>
#include <utility>
#include <vector>
#include <memory>
#include <functional>
#include "AnonymizedMessage.h"
namespace audacity
{
namespace sentry
{
//! Additional payload to the exception
using ExceptionData = std::pair<std::string, AnonymizedMessage>;
//! 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<ExceptionData> 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<AnonymizedMessage> 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<void (int httpCode, std::string responseBody)>;
//! 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<ReportImpl> mImpl;
};
} // namespace sentry
} // namespace audacity

View File

@ -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 <chrono>
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<seconds>(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

View File

@ -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 <string>
#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

View File

@ -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}

View File

@ -959,10 +959,6 @@ list( APPEND SOURCES
widgets/ReadOnlyText.h
widgets/Ruler.cpp
widgets/Ruler.h
$<$<BOOL:${${_OPT}has_sentry_reporting}>:
widgets/ErrorReportDialog.cpp
widgets/ErrorReportDialog.h
>
widgets/Warning.cpp
widgets/Warning.h
widgets/WindowAccessible.cpp

View File

@ -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.

View File

@ -1,221 +0,0 @@
/**********************************************************************
Audacity: A Digital Audio Editor
ErrorReportDialog.cpp
Dmitry Vedenko
**********************************************************************/
#include "ErrorReportDialog.h"
#include <wx/app.h>
#include <wx/artprov.h>
#include <wx/button.h>
#include <wx/collpane.h>
#include <wx/dialog.h>
#include <wx/html/htmlwin.h>
#include <wx/icon.h>
#include <wx/intl.h>
#include <wx/settings.h>
#include <wx/sizer.h>
#include <wx/statbmp.h>
#include <wx/stattext.h>
#include <wx/statusbr.h>
#include <wx/textctrl.h>
#include <wx/bmpbuttn.h>
#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<audacity::sentry::Report> (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();
}

View File

@ -1,69 +0,0 @@
/**********************************************************************
Audacity: A Digital Audio Editor
ErrorReportDialog.h
Dmitry Vedenko
**********************************************************************/
#ifndef __AUDACITY_SENTRYERRORDIALOG__
#define __AUDACITY_SENTRYERRORDIALOG__
#include <memory>
#include <wx/defs.h>
#include <wx/msgdlg.h>
#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<audacity::sentry::Report> 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__