feat: Add SentrySDK.lastRunStatus to distinguish unknown, no-crash and crash#7469
feat: Add SentrySDK.lastRunStatus to distinguish unknown, no-crash and crash#7469
SentrySDK.lastRunStatus to distinguish unknown, no-crash and crash#7469Conversation
…& crash SentrySDK.crashedLastRun returns false both when the app didn't crash and when the status is unknown (before SDK init). This adds SentrySDK.lastRunStatus returning a tri-state enum (.unknown, .didNotCrash, .didCrash) and an onLastRunStatus callback that fires regardless of crash outcome. The old crashedLastRun and onCrashedLastRun are deprecated. Closes #4958
Semver Impact of This PR🟡 Minor (new features) 📋 Changelog PreviewThis is how your changes will appear in the changelog. New Features ✨
Bug Fixes 🐛
Internal Changes 🔧Deps
Samples
Other
🤖 This preview updates automatically when you update the PR. |
|
| @available(*, deprecated, message: "Use onLastRunStatus instead, which is called regardless of whether the app crashed.") | ||
| @objc public var onCrashedLastRun: SentryOnCrashedLastRunCallback? | ||
|
|
||
| /// A block called shortly after the initialization of the SDK when the crash status of the |
There was a problem hiding this comment.
Not sure if there's enough value in also calling it for normal program execution (not crashed), but added if for completnes sake. If we don't need it, we keep calling onCrashedLastRun like before and not deprecate it.
Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 795e128 | 1216.68 ms | 1245.83 ms | 29.15 ms |
| 0e4a9dc | 1222.92 ms | 1255.78 ms | 32.86 ms |
| 7e30a5e | 1214.57 ms | 1247.78 ms | 33.21 ms |
| 79e2bb8 | 1216.37 ms | 1242.42 ms | 26.05 ms |
| 64e79c5 | 1217.59 ms | 1243.98 ms | 26.39 ms |
| 6108e4c | 1212.31 ms | 1251.80 ms | 39.49 ms |
| 84bc307 | 1211.52 ms | 1237.09 ms | 25.56 ms |
| fee8669 | 1220.50 ms | 1231.84 ms | 11.34 ms |
| 80963bd | 1194.76 ms | 1212.13 ms | 17.38 ms |
| e03f459 | 1222.56 ms | 1255.94 ms | 33.37 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 795e128 | 24.14 KiB | 1.10 MiB | 1.08 MiB |
| 0e4a9dc | 24.14 KiB | 1.11 MiB | 1.09 MiB |
| 7e30a5e | 24.14 KiB | 1.10 MiB | 1.08 MiB |
| 79e2bb8 | 24.14 KiB | 1.04 MiB | 1.02 MiB |
| 64e79c5 | 24.14 KiB | 1.11 MiB | 1.09 MiB |
| 6108e4c | 24.14 KiB | 1.11 MiB | 1.09 MiB |
| 84bc307 | 24.14 KiB | 1.08 MiB | 1.06 MiB |
| fee8669 | 24.14 KiB | 1.10 MiB | 1.08 MiB |
| 80963bd | 24.14 KiB | 1.11 MiB | 1.09 MiB |
| e03f459 | 24.14 KiB | 1.11 MiB | 1.09 MiB |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #7469 +/- ##
========================================
Coverage ? 85.995%
========================================
Files ? 484
Lines ? 28820
Branches ? 12519
========================================
Hits ? 24784
Misses ? 3988
Partials ? 48
Continue to review full report in Codecov by Sentry.
|
There was a problem hiding this comment.
Pull request overview
This pull request adds a new tri-state enum SentryLastRunStatus to address the limitation of the boolean crashedLastRun property, which could not distinguish between "did not crash" and "unknown" (before SDK initialization). The change is backward compatible, with the old APIs deprecated but still functional.
Changes:
- Adds
SentryLastRunStatusenum with three cases:.unknown,.didNotCrash, and.didCrash - Adds
SentrySDK.lastRunStatusproperty that returns the tri-state enum - Adds
Options.onLastRunStatuscallback that is invoked regardless of crash status (unlike the old callback which only fired on crashes) - Deprecates
SentrySDK.crashedLastRunandOptions.onCrashedLastRunwith clear migration guidance
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| Sources/Swift/Helper/SentryLastRunStatus.swift | Defines new SentryLastRunStatus enum with documentation and CustomStringConvertible conformance |
| Sources/Swift/Helper/SentrySDK.swift | Adds lastRunStatus property and deprecates crashedLastRun with migration guidance |
| Sources/Swift/Options.swift | Adds onLastRunStatus callback and deprecates onCrashedLastRun |
| Sources/Sentry/include/SentrySDKInternal.h | Updates Objective-C header with new lastRunStatus property and deprecation markers |
| Sources/Sentry/include/SentrySDK+Private.h | Renames crashedLastRunCalled to lastRunStatusCalled and adds crashReporterInstalled flag |
| Sources/Sentry/SentrySDKInternal.m | Implements lastRunStatus with proper state checking and resets flags in close() |
| Sources/Sentry/SentryOptionsInternal.m | Adds options parsing for onLastRunStatus callback |
| Sources/Sentry/SentryClient.m | Updates callback invocation to call both old and new callbacks for backward compatibility |
| Sources/Swift/Integrations/SentryCrash/SentryCrashIntegration.swift | Sets crashReporterInstalled flag and calls onLastRunStatus callback for non-crash scenarios |
| Tests/SentryTests/SentrySDKTests.swift | Adds tests for lastRunStatus in various states |
| Tests/SentryTests/SentryOptionsTest.m | Adds tests for onLastRunStatus options parsing |
| Tests/SentryTests/SentryClientTests.swift | Adds comprehensive tests for onLastRunStatus callback behavior |
| Tests/SentryTests/Integrations/SentryCrash/SentryCrashIntegrationTests.swift | Adds tests for integration's handling of onLastRunStatus |
| SentryTestUtils/Sources/ClearTestState.swift | Updates test cleanup to reset new flags |
| Samples/SentrySampleShared/SentrySampleShared/SentrySDKWrapper.swift | Demonstrates new API usage with logging |
| CHANGELOG.md | Adds feature entry |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Tests/SentryTests/Integrations/SentryCrash/SentryCrashIntegrationTests.swift
Show resolved
Hide resolved
Sentry Build Distribution
|
Sentry Build Distribution
|
Sentry Build Distribution
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| if !SentryDependencyContainer.sharedInstance().crashWrapper.crashedLastLaunch, let callback = options?.onLastRunStatusDetermined { | ||
| SentrySDKInternal.lastRunStatusCalled = true | ||
| callback(.didNotCrash, nil) | ||
| } |
There was a problem hiding this comment.
No-crash callback silently suppresses deprecated callback for fatal events
Medium Severity
When both onLastRunStatusDetermined and the deprecated onCrashedLastRun are set and the crash reporter reports no crash, lastRunStatusCalled is set to true in the integration. If a non-crash-reporter fatal event (like a watchdog termination) arrives later in SentryClient, the !lastRunStatusCalled guard causes the entire block to be skipped — silently suppressing the deprecated onCrashedLastRun callback that would have fired before this change. Previously, crashedLastRunCalled was only set inside SentryClient when onCrashedLastRun was non-nil, so it never blocked later fatal events when only the deprecated callback was in use alongside no early flag-setting code.
Additional Locations (1)
Sentry Build Distribution
|
itaybre
left a comment
There was a problem hiding this comment.
LGTM, I am fine with resetting lastRunStatusCalled status.
Maybe just add a note regarding the expected behavior
| [SentrySDKInternal setCurrentHub:nil]; | ||
|
|
||
| crashReporterInstalled = NO; | ||
| lastRunStatusCalled = NO; |
There was a problem hiding this comment.
l: This means that closing and starting the SDK will call onLastRunStatus again right?
But in theory it will always return false (if the SDK closed and started again, it would be old to have crashed)
There was a problem hiding this comment.
Good catch, i will check & address this.


📜 Description
SentrySDK.crashedLastRun returns false both when the app didn't crash and when the status is unknown (before SDK init). This adds SentrySDK.lastRunStatus returning a tri-state enum (.unknown, .didNotCrash, .didCrash) and an onLastRunStatus callback that fires regardless of crash outcome. The old crashedLastRun and onCrashedLastRun are deprecated.
💡 Motivation and Context
Closes #4958
💚 How did you test it?
Unit tests + added logging in sample app.
📝 Checklist
You have to check all boxes before merging:
sendDefaultPIIis enabled.