Skip to content

feat(session-replay): upload replay envelope on crash with crashpad, breakpad and inproc backends#1842

Merged
tustanivsky merged 3 commits into
masterfrom
feat/replay-env-all-backends
Jul 6, 2026
Merged

feat(session-replay): upload replay envelope on crash with crashpad, breakpad and inproc backends#1842
tustanivsky merged 3 commits into
masterfrom
feat/replay-env-all-backends

Conversation

@tustanivsky

Copy link
Copy Markdown
Collaborator

This PR adds session-replay envelope upload during crash handling for the crashpad (Windows/Linux), breakpad, and inproc backends, extending the native-crash-daemon-only implementation from #1809 to all backends.

The delivery model differs from the daemon: since these backends handle the crash in a dying process (or, for crashpad, hand off to a handler process that only performs multipart minidump uploads), the crash handler consumes the staged <database>/replays/replay-<id>.{mp4,json} files at crash time and persists the resulting replay_video envelope into the run directory via the disk transport. sentry__process_old_runs then uploads it on the next launch. Because the staged replay files are consumed during crash handling, embedders that clear replays/ before sentry_init (e.g. sentry-unreal) remain unaffected.

Key changes

  • breakpad / inproc

    • After the crash envelope is prepared in breakpad_backend_callback / process_ucontext_deferred, flush the pending replay through a run-directory disk transport.
    • Source the replay_id from the scope-applied crash event (contexts.replay.replay_id).
    • Execute the flush before dispatching to an external crash reporter so the replay is included on that path as well.
  • crashpad (first-chance handler, Windows/Linux)

    • Perform the same run-directory disk transport flush after the session dump.
    • Take an additional reference on the crash event before flush_scope_from_handler, since flush_scope_to_event releases its reference. The scope-applied event is then used to source the replay flush.
  • src/sentry_session_replay.h

    • Updated the documentation from "native-daemon-only" to describe both delivery modes:
      • live transport (same-session)
      • run-directory disk transport (next launch)
    • sentry__session_replay_flush_pending itself is unchanged, as it was already transport-agnostic.
  • Tests

    • Moved REPLAY_ID, stage_replay(), and is_replay_envelope() into shared test helpers (tests/__init__.py).
    • Factored envelope validation into assert_replay_envelope() (tests/assertions.py).
    • Fixed test_native_replay_orphan_not_flushed, which incorrectly passed an Envelope where raw bytes were expected, making its no-replay assertion vacuously true.

Testing

  • Added test_crash_replay_envelope_http (parameterized over inproc and breakpad):

    • Crash with a staged replay.
    • Verify staged replay files are consumed during crash handling.
    • Verify the next launch uploads both the crash envelope and a fully validated replay_video envelope.
  • Added test_crashpad_replay_envelope:

    • Verify same-session minidump upload.
    • Verify next-launch replay_video envelope upload.
    • Assert staged replay files are consumed during crash handling.
    • Skipped on macOS (no SetFirstChanceExceptionHandler).
  • Existing native-daemon tests (test_native_replay_envelope, test_native_replay_orphan_not_flushed) continue to pass unchanged using the refactored helpers.

  • Verified locally on Windows (MSVC).

Related items

Known limitations

  • macOS Crashpad and Windows WER/fast-fail crashes do not include replay data because no in-process hook executes.

#skip-changelog

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 7a17df3

@tustanivsky tustanivsky merged commit b84164b into master Jul 6, 2026
66 checks passed
@tustanivsky tustanivsky deleted the feat/replay-env-all-backends branch July 6, 2026 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants