mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-11 12:33:25 -08:00
[Crash] Add lifecycle breadcrumbs for unattributable native crashes
Co-authored-by: sentry[bot] <39604003+sentry[bot]@users.noreply.github.com>
This commit is contained in:
parent
40ebd22549
commit
59db732abd
6 changed files with 61 additions and 0 deletions
|
|
@ -614,3 +614,19 @@ QString CrashReporter::redactCockatriceUrls(const QString &line)
|
||||||
redacted.append(line.mid(pos));
|
redacted.append(line.mid(pos));
|
||||||
return redacted;
|
return redacted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CrashReporter::addBreadcrumb(const char *category, const char *message)
|
||||||
|
{
|
||||||
|
#if COCKATRICE_WITH_CRASH_REPORTING
|
||||||
|
if (category == nullptr || message == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sentry_value_t crumb = sentry_value_new_breadcrumb("default", message);
|
||||||
|
sentry_value_set_by_key(crumb, "category", sentry_value_new_string(category));
|
||||||
|
sentry_value_set_by_key(crumb, "level", sentry_value_new_string("info"));
|
||||||
|
sentry_add_breadcrumb(crumb);
|
||||||
|
#else
|
||||||
|
Q_UNUSED(category);
|
||||||
|
Q_UNUSED(message);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -167,6 +167,17 @@ public:
|
||||||
static QString sanitizeLogLine(const QString &line);
|
static QString sanitizeLogLine(const QString &line);
|
||||||
static QString redactCockatriceUrls(const QString &line);
|
static QString redactCockatriceUrls(const QString &line);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Record a fixed-text lifecycle breadcrumb on the active Sentry scope.
|
||||||
|
*
|
||||||
|
* Native crashes whose stack walk loses the in-app frames (e.g. a QMap lookup
|
||||||
|
* that dies inside Qt's string comparison) otherwise arrive with no hint of
|
||||||
|
* what the client was doing. Only pass compile-time string literals: no user
|
||||||
|
* names, card names, paths or URLs, so no personal data can leak through this
|
||||||
|
* channel. Thread-safe; a no-op in OFF builds or before init().
|
||||||
|
*/
|
||||||
|
static void addBreadcrumb(const char *category, const char *message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool ready = false;
|
bool ready = false;
|
||||||
QString sentryDatabasePath;
|
QString sentryDatabasePath;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "user_list_widget.h"
|
#include "user_list_widget.h"
|
||||||
|
|
||||||
|
#include "../../../../client/crash/crash_reporter.h"
|
||||||
#include "../../../../client/settings/cache_settings.h"
|
#include "../../../../client/settings/cache_settings.h"
|
||||||
#include "../../interface/pixel_map_generator.h"
|
#include "../../interface/pixel_map_generator.h"
|
||||||
#include "../../interface/theme_manager.h"
|
#include "../../interface/theme_manager.h"
|
||||||
|
|
@ -1221,6 +1222,7 @@ void UserListWidget::processUserInfo(Section section, const ServerInfo_User &use
|
||||||
|
|
||||||
bool UserListWidget::deleteUser(const QString &userName)
|
bool UserListWidget::deleteUser(const QString &userName)
|
||||||
{
|
{
|
||||||
|
CrashReporter::addBreadcrumb("users", "user list row removed");
|
||||||
if (sectioned) {
|
if (sectioned) {
|
||||||
// The user may own several rows (one per section). Drop them all.
|
// The user may own several rows (one per section). Drop them all.
|
||||||
bool removed = false;
|
bool removed = false;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "tab_supervisor.h"
|
#include "tab_supervisor.h"
|
||||||
|
|
||||||
|
#include "../../../client/crash/crash_reporter.h"
|
||||||
#include "../../../client/settings/cache_settings.h"
|
#include "../../../client/settings/cache_settings.h"
|
||||||
#include "../../../client/settings/shortcuts_settings.h"
|
#include "../../../client/settings/shortcuts_settings.h"
|
||||||
#include "../../intents/contexts/context_connect_to_server.h"
|
#include "../../intents/contexts/context_connect_to_server.h"
|
||||||
|
|
@ -593,6 +594,7 @@ void TabSupervisor::startLocal(const QList<AbstractClient *> &_clients)
|
||||||
*/
|
*/
|
||||||
void TabSupervisor::stop()
|
void TabSupervisor::stop()
|
||||||
{
|
{
|
||||||
|
CrashReporter::addBreadcrumb("tabs", "tab supervisor stopping");
|
||||||
if ((!client) && localClients.isEmpty()) {
|
if ((!client) && localClients.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1003,6 +1005,7 @@ void TabSupervisor::updateLatencyTooltip(const LatencyTracker::Stats &stats)
|
||||||
|
|
||||||
void TabSupervisor::gameJoined(const Event_GameJoined &event)
|
void TabSupervisor::gameJoined(const Event_GameJoined &event)
|
||||||
{
|
{
|
||||||
|
CrashReporter::addBreadcrumb("tabs", "game joined");
|
||||||
QMap<int, QString> roomGameTypes;
|
QMap<int, QString> roomGameTypes;
|
||||||
TabRoom *room = roomTabs.value(event.game_info().room_id());
|
TabRoom *room = roomTabs.value(event.game_info().room_id());
|
||||||
if (room) {
|
if (room) {
|
||||||
|
|
@ -1055,6 +1058,7 @@ void TabSupervisor::gameLeft(TabGame *tab)
|
||||||
|
|
||||||
void TabSupervisor::addRoomTab(const ServerInfo_Room &info, bool setCurrent)
|
void TabSupervisor::addRoomTab(const ServerInfo_Room &info, bool setCurrent)
|
||||||
{
|
{
|
||||||
|
CrashReporter::addBreadcrumb("tabs", "room tab added");
|
||||||
auto *tab = new TabRoom(this, client, userInfo, info);
|
auto *tab = new TabRoom(this, client, userInfo, info);
|
||||||
connect(tab, &TabRoom::maximizeClient, this, &TabSupervisor::maximizeMainWindow);
|
connect(tab, &TabRoom::maximizeClient, this, &TabSupervisor::maximizeMainWindow);
|
||||||
connect(tab, &TabRoom::roomClosing, this, &TabSupervisor::roomLeft);
|
connect(tab, &TabRoom::roomClosing, this, &TabSupervisor::roomLeft);
|
||||||
|
|
@ -1472,6 +1476,7 @@ void TabSupervisor::actShowPopup(const QString &message)
|
||||||
|
|
||||||
void TabSupervisor::processUserLeft(const QString &userName)
|
void TabSupervisor::processUserLeft(const QString &userName)
|
||||||
{
|
{
|
||||||
|
CrashReporter::addBreadcrumb("users", "user left");
|
||||||
TabMessage *tab = messageTabs.value(userName);
|
TabMessage *tab = messageTabs.value(userName);
|
||||||
if (tab) {
|
if (tab) {
|
||||||
tab->processUserLeft();
|
tab->processUserLeft();
|
||||||
|
|
|
||||||
|
|
@ -427,6 +427,23 @@ int main(int argc, char *argv[])
|
||||||
CardDatabaseManager::setCardDatabasePathProvider(&SettingsCache::instance());
|
CardDatabaseManager::setCardDatabasePathProvider(&SettingsCache::instance());
|
||||||
CardDatabaseManager::setCardSetPriorityController(&SettingsCache::instance().cardDatabase());
|
CardDatabaseManager::setCardSetPriorityController(&SettingsCache::instance().cardDatabase());
|
||||||
|
|
||||||
|
// Lifecycle breadcrumbs for native crash reports (see COCKATRICE-DESKTOP-1R): the live
|
||||||
|
// card maps are replaced wholesale on reset, so knowing whether a crash followed a reload
|
||||||
|
// narrows down which QMap was being read. Direct connections: the SDK call is thread-safe
|
||||||
|
// and loading signals may come from a QtConcurrent worker.
|
||||||
|
{
|
||||||
|
CardDatabase *crumbDb = CardDatabaseManager::getInstance();
|
||||||
|
QObject::connect(
|
||||||
|
crumbDb, &CardDatabase::cardDatabaseReset, crumbDb,
|
||||||
|
[] { CrashReporter::addBreadcrumb("card_db", "card database snapshot swapped in"); }, Qt::DirectConnection);
|
||||||
|
QObject::connect(
|
||||||
|
crumbDb, &CardDatabase::cardDatabaseLoadingFinished, crumbDb,
|
||||||
|
[] { CrashReporter::addBreadcrumb("card_db", "card database loading finished"); }, Qt::DirectConnection);
|
||||||
|
QObject::connect(
|
||||||
|
crumbDb, &CardDatabase::cardDatabaseLoadingFailed, crumbDb,
|
||||||
|
[] { CrashReporter::addBreadcrumb("card_db", "card database loading failed"); }, Qt::DirectConnection);
|
||||||
|
}
|
||||||
|
|
||||||
qCInfo(MainLog) << "Starting main program";
|
qCInfo(MainLog) << "Starting main program";
|
||||||
|
|
||||||
// Front-load the card database before constructing the main window. The
|
// Front-load the card database before constructing the main window. The
|
||||||
|
|
|
||||||
|
|
@ -418,6 +418,16 @@ TEST(CrashReporterTest, BeginSessionEndSessionRoundTripReportsClean)
|
||||||
reporter.endSession();
|
reporter.endSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(CrashReporterTest, AddBreadcrumbIsSafeWithoutInitAndWithNullArguments)
|
||||||
|
{
|
||||||
|
// Breadcrumbs are emitted from GUI slots and QtConcurrent workers regardless of whether
|
||||||
|
// the SDK was initialised (empty DSN, Never consent, OFF builds); none of these may crash.
|
||||||
|
CrashReporter::addBreadcrumb("card_db", "card database snapshot swapped in");
|
||||||
|
CrashReporter::addBreadcrumb(nullptr, "message");
|
||||||
|
CrashReporter::addBreadcrumb("category", nullptr);
|
||||||
|
SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue