Files
AyeZeeBB 571d57f603 Crash reports: sent as envelopes so their logs arrive, with the log's last lines, crash site and mods
Sentry's minidump endpoint streams every attachment but the dump to an object store, which this
self-hosted Sentry does not run: ReSkate.log and report.json were dropped from every crash
(outcome upload_failed). Each crash now goes to the envelope endpoint as sentry-native sends one:
the event, the minidump, report.json and the log, all kept.

- The event carries the log's last 100 lines as breadcrumbs (debug lines only among the last 25),
  the mods the game ran with (enabled, outdated, excluded), how long it had run, and an anonymous
  install ID as its user. Its time is the crash's, however late it is sent.
- crash.site tags where it crashed ("Skate.exe+0x3d9ed9d"), as Sentry names game code by the
  nearest export; mods.count how many mods were on.
- An accepted report is kept in sent/ (the newest 10) instead of deleted, so the player still has
  their crashes.
- multipart.* is report_envelope.*; the receipt check also reads the envelope endpoint's
  {"id": ...}.
2026-10-16 17:59:40 -05:00

35 lines
2.0 KiB
C++

#pragma once
#include "Engine/Core/Json/json.h"
#include <cstddef>
#include <filesystem>
#include <string>
// What a crash report carries to Sentry besides its tags and attachments. Attachments (the log)
// are kept only where the server stores them; these go in the event itself, which it always does.
namespace dingosdk::crash_report {
// <dump>.event.json: the report's event fields other than tags and release (breadcrumbs,
// contexts, user), merged into the event when it is sent.
std::filesystem::path event_details_path(const std::filesystem::path& dump);
inline constexpr std::size_t max_event_details_bytes = 512 * 1024;
// The log's last lines as Sentry breadcrumbs ({"values": [...]}, oldest first): up to `count`
// lines, the debug ones only among the last `recent` (what happened just before is worth all of
// it; further back only what was said above debug). Each line's time, source, level and text.
Json log_breadcrumbs(const std::filesystem::path& log, std::size_t count = 100, std::size_t recent = 25) noexcept;
// Where the dump's exception happened, as "<module file name>+0x<offset>", or empty when the dump
// does not say (no exception, or an address outside every module).
std::string crash_site(const std::filesystem::path& dump) noexcept;
// An ID for this install, random and made once, kept in <directory>/install-id.txt: tells one
// player's crashes from another's without saying who they are. Empty when it cannot be kept.
std::string install_id(const std::filesystem::path& directory) noexcept;
// An accepted report's files go to <its folder>/sent, which keeps the newest `keep` reports: the
// player keeps their crashes after they are sent, whatever the server keeps.
inline constexpr std::size_t kept_sent_reports = 10;
void keep_sent_report(const std::filesystem::path& dump, std::size_t keep = kept_sent_reports) noexcept;
// Every file a queued report has (the dump, its tags, log and event details).
void remove_report_files(const std::filesystem::path& dump) noexcept;
}