feat(crash-reporting): opt-in crash reporting behind a build-time SENTRY_DSN gate#878
Open
TaprootFreak wants to merge 3 commits into
Open
feat(crash-reporting): opt-in crash reporting behind a build-time SENTRY_DSN gate#878TaprootFreak wants to merge 3 commits into
TaprootFreak wants to merge 3 commits into
Conversation
Contributor
Author
|
3 review passes until zero findings. Pass 1 fixes: made the reporter init best-effort (a failing or misconfigured reporter can no longer block app startup — with a dedicated test), moved the release-mode splash preserve ahead of the first await, corrected the handler-chaining description to match the pinned SDK version's actual behavior, additionally pinned session tracking off and narrowed the pinning claim to the exact option list, fixed the test-file import order, and removed an internal record reference from the PR description. Pass 2 fix: restored installErrorHandlers() as the very first bootstrap step so its documented guarantee holds while still leaving no async gap before the splash preserve. Pass 3: clean. |
TaprootFreak
marked this pull request as ready for review
July 24, 2026 16:11
This was referenced Jul 24, 2026
TaprootFreak
added a commit
that referenced
this pull request
Jul 24, 2026
## Summary - inject the repository `SENTRY_DSN` into Android and iOS store builds with an explicit `production`/`internal` environment - keep compile-time values out of Fastlane process arguments via a mode-0600 temporary define file and fail release builds when the DSN is missing - upload Android split debug info, Dart obfuscation maps, and iOS archive symbols to the self-hosted Sentry project - identify uploads with the native release name `swiss.realunit.app@<version>+<build>` and matching distribution The Sentry project `realunitchapp` and the repository secrets `SENTRY_DSN` and `SENTRY_AUTH_TOKEN` have been provisioned. Runtime reporting activates together with #878. Related to DFXServer/server#958. ## Validation - Ruby syntax checks for both Fastfiles - workflow YAML parse and `git diff --check` - `flutter analyze --no-fatal-infos` - non-golden Flutter suite: 4,687 tests passed; the 16 subprocess cases initially failed only because local `dart` was absent from PATH and all 16 passed when rerun with the Flutter SDK path - DFX PR precheck: 3 rounds, final conformity and logic reviews both at 0 findings ## Follow-up verification The first tagged native release should confirm the uploaded debug files in Sentry and symbolicate one controlled test event. --------- Co-authored-by: Daniel Padrino <danswarrior1@gmail.com>
…TRY_DSN gate Customer-facing crashes currently leave no diagnostic trace: errors from Future/Stream/Timer callbacks vanish, and support cases arrive with zero evidence (#866 documents the gap). This wires the crash reporter into the existing error-handler hook. Without --dart-define=SENTRY_DSN (all local, test and current CI builds) the SDK never starts and produces no network traffic. The option set is pinned to error events only: no PII, no screenshots, no view hierarchy, no tracing. initCrashReporting() runs after installErrorHandlers() on purpose - the SDK chains the handlers installed there, the reverse order would drop its async hook. CONTRIBUTING gains the one scoped API-access exception for first-party crash reporting; widening the reported data is declared review-blocking. The release pipeline change that injects the DSN is a deliberate follow-up so this change stays inert and reviewable on its own.
…pinning Review pass fixes: - initCrashReporting is best-effort now: a malformed DSN or failing native binding is logged and swallowed instead of aborting app startup as an unhandled error before runApp. - Preserve the native splash before the first await in main() so the new async gap cannot flash the splash to blank in release builds. - Correct the handler-chaining doc: the SDK's PlatformDispatcher.onError hook delegates first and captures second (FlutterError.onError is the capture-first one); the ordering requirement itself is unchanged. - Narrow the pinning claim to the exact option list and additionally pin enableAutoSessionTracking=false - error events only, no session pings. - Test-file import order per CONTRIBUTING (package:other before package:realunit_wallet).
…erve again
installErrorHandlers() is fully synchronous, so running it ahead of the
release-mode splash preserve keeps the documented guarantee in
error_handlers.dart ('called before any other bootstrap step') true while
still leaving no async gap before FlutterNativeSplash.preserve().
TaprootFreak
force-pushed
the
feat/crash-reporting-dsn-gate
branch
from
July 24, 2026 19:53
9653f93 to
74cbb18
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Two customer cases this week reached support with zero diagnostic evidence: a BitBox02 USB connect crash/hang on Android and a registration-signing blocker (both 23.07.). Server-side request tracing covers everything that reaches the API — but a client-side crash before any request is invisible. The app has no crash reporter; every error thrown from a
Future,StreamorTimercallback vanishes without trace (#866 documents this gap explicitly, andinstallErrorHandlers()was designed as the hook a reporter plugs into).Change
sentry_flutterbehind a compile-time gate.initCrashReporting()(new,lib/setup/error_handling/crash_reporting.dart) reads--dart-define=SENTRY_DSN. Without an injected DSN — i.e. in every local, test and current CI build — the SDK never starts and produces no network traffic. The app behaves exactly as before this PR.initCrashReporting()— reporting infrastructure can never keep the wallet from starting. Covered by a dedicated test.main()callsinitCrashReporting()afterinstallErrorHandlers(), becauseinstallErrorHandlers()overwritesPlatformDispatcher.onErrorwithout chaining — the reverse order would silently drop the SDK's async-error hook. The SDK itself chains both handlers it wraps (FlutterError.onError: capture, then delegate;PlatformDispatcher.onError: delegate, then capture). In release mode the native splash is now preserved before this first await, so the added async gap cannot flash the splash to blank.sendDefaultPii=false,attachScreenshot=false,enableAutoSessionTracking=false,tracesSampleRate=null— error events only, no session telemetry. Native crash handling and ANR detection deliberately stay on their SDK defaults: they produce precisely the error events this reporter exists for. View-hierarchy attachment stays off by SDK default; its option is experimental and deliberately not referenced. Environment defaults toproduction, overridable via--dart-define=SENTRY_ENVIRONMENT.Tests
test/setup/error_handling/crash_reporting_test.dart: DSN gate (no-op without DSN, exactly one init with DSN), the full pinned option set, and the swallow-on-failure contract, via the injectableCrashReporterInit— no platform channels involved.// @no-integration-testannotation oninitCrashReportingper CONTRIBUTING: the native SDK only starts in builds that inject a DSN, which no test build does.Open points before this becomes effective
SENTRY_DSN(repo/environment secret +--dart-define) — deliberately a separate PR, so this one stays inert and fully reviewable on its own.