feat(android): [Unhandled Sessions 3] Add internal non-terminating envelope capture - #5921
feat(android): [Unhandled Sessions 3] Add internal non-terminating envelope capture#5921buenaflor wants to merge 8 commits into
Conversation
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
|
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
📲 Install BuildsAndroid
|
Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 6b019b7 | 343.31 ms | 417.23 ms | 73.91 ms |
| d15471f | 286.65 ms | 314.68 ms | 28.03 ms |
| d217708 | 409.83 ms | 474.72 ms | 64.89 ms |
| d500866 | 326.13 ms | 378.70 ms | 52.58 ms |
| fcec2f2 | 314.96 ms | 373.66 ms | 58.70 ms |
| d501a7e | 314.55 ms | 343.34 ms | 28.79 ms |
| 7414e9b | 322.49 ms | 378.88 ms | 56.39 ms |
| fcec2f2 | 357.47 ms | 447.32 ms | 89.85 ms |
| a416a65 | 316.52 ms | 359.67 ms | 43.15 ms |
| 983e0f0 | 350.64 ms | 386.44 ms | 35.79 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 6b019b7 | 0 B | 0 B | 0 B |
| d15471f | 1.58 MiB | 2.13 MiB | 559.54 KiB |
| d217708 | 1.58 MiB | 2.10 MiB | 532.97 KiB |
| d500866 | 0 B | 0 B | 0 B |
| fcec2f2 | 1.58 MiB | 2.12 MiB | 551.50 KiB |
| d501a7e | 0 B | 0 B | 0 B |
| 7414e9b | 0 B | 0 B | 0 B |
| fcec2f2 | 1.58 MiB | 2.12 MiB | 551.50 KiB |
| a416a65 | 1.58 MiB | 2.12 MiB | 555.26 KiB |
| 983e0f0 | 0 B | 0 B | 0 B |
Previous results on branch: feat/unhandled-sessions-internal-api
Startup times
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| f4f202f | 315.94 ms | 369.24 ms | 53.30 ms |
| 8014a1f | 304.46 ms | 376.38 ms | 71.92 ms |
| ed254d0 | 331.02 ms | 359.08 ms | 28.06 ms |
| bc96797 | 321.86 ms | 377.38 ms | 55.52 ms |
| b696cfd | 320.00 ms | 358.66 ms | 38.66 ms |
| 075631e | 355.90 ms | 458.42 ms | 102.52 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| f4f202f | 0 B | 0 B | 0 B |
| 8014a1f | 0 B | 0 B | 0 B |
| ed254d0 | 0 B | 0 B | 0 B |
| bc96797 | 0 B | 0 B | 0 B |
| b696cfd | 0 B | 0 B | 0 B |
| 075631e | 0 B | 0 B | 0 B |
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
6 similar comments
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
56ab999 to
1906ec6
Compare
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
2 similar comments
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
06f5823 to
ae23921
Compare
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
ae23921 to
b2ff9d9
Compare
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
b2ff9d9 to
945602b
Compare
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
Hybrid runtimes such as Flutter report unhandled exceptions that do not terminate the process. Routing those through captureEnvelope ends the session as crashed and starts a replacement one, which understates crash-free session rates. The new entry point keeps the session alive with the same id, increments its error count, and marks it pending-unhandled so it finalizes as unhandled at its natural end. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…thods Both methods scanned the envelope's events to derive the same pair of booleans, but wrote it differently - one via isCrashed(), the other via getUnhandledException() != null, which is the same predicate. Extract a single scanEvents returning NONE/ERRORED/UNHANDLED so the two agree by construction and an unhandled-but-not-errored state is unrepresentable. Co-authored-by: Cursor <cursoragent@cursor.com>
The annotation had no mechanical effect: apiValidation configures only ignoredPackages/ignoredProjects and no nonPublicMarkers, so the type is tracked in sentry.api either way. Regenerating the dump after removing it produces no diff. The interface still has to be public, since the lambda in InternalSentrySdk.captureEnvelopeNonTerminating targets it from io.sentry.android.core. Co-authored-by: Cursor <cursoragent@cursor.com>
945602b to
91be174
Compare
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
Both the method and the enum were plural nouns that read as if they returned the envelope's events, when they return a single summary value. That made "events != EnvelopeEvents.NONE" look like an emptiness check rather than "nothing worth recording happened". EnvelopeEventState also lines up with the Session.State vocabulary already used here. Co-authored-by: Cursor <cursoragent@cursor.com>
🚨 Detected changes in high risk code 🚨High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:
|
PR Stack (Unhandled Sessions)
📜 Description
Adds
InternalSentrySdk.captureEnvelopeNonTerminating(byte[])for hybrid runtimes where an unhandled exception does not terminate the process.Unlike
captureEnvelope(byte[], boolean), it does not treathandled=falseas a crash. Instead it:Okwith the same session id on the scope,The session is finalized later by normal lifecycle (
endSession, background, or previous-session recovery) asunhandled, unless a native crash escalates it tocrashed.captureEnvelope(byte[], boolean)is unchanged.Also in this PR:
Scope.IWithSessionbecomes public soInternalSentrySdkcan mutate the session under the scope lock; it is the only consumer. Its@ApiStatus.Internalwas dropped as inert —sentry.apitracks the type either way.scanEvents, replacing two loops that computed the same booleans by different routes, plus a sharedreadEnvelope.catch (Throwable)narrowed tocatch (Exception)soOutOfMemoryErrorand friends propagate instead of being swallowed.💡 Motivation and Context
Flutter forwards
handled=falseevents through the terminating hybrid capture path. That marks the sessioncrashedand may start a replacement session even though the Flutter process keeps running, incorrectly lowering crash-free session rates.💚 How did you test it?
New
InternalSentrySdkTestcoverage: the session stayingOkwith the same id and the flag persisted to disk;endSessionafterwards finalizing asunhandled; and a later hard crash finalizing the old session ascrashedand starting a freshOksession. ExistingcaptureEnvelopetests confirm that path is unchanged.📝 Checklist
sendDefaultPIIis enabled.🔮 Next steps
Update the Flutter Android bridge to use
captureEnvelopeNonTerminatingfor non-terminating unhandled events.