fix(anr): Use Proguard ID from origination ANR process with ANR profie chunks - #5852
Merged
Conversation
…le chunks We report ANRs from the app process launched _after_ the ANR occurs. Usually the same app installation is used to launch both processes and so the Proguard ID is the same for each. But not always! The user could have installed a new version of the app in between, so we need to make sure we grab the Proguard ID associated with the original process. Prior to this commit, we would always use the originating Proguard ID with the ANR event but not with the linked ANR profile chunk. Instead, the profile chunk would always use the current process Proguard ID. This commit fixes that by updating the profile chunk pipeline so it respects any incoming debug images (including Proguard ones) in the DebugMeta bound to the profile chunk passed to IScopes.createProfileChunk().
0xadam-brown
force-pushed
the
fix/anr-deobfuscation
branch
from
July 29, 2026 10:38
28c28de to
75a9e65
Compare
📲 Install BuildsAndroid
|
0xadam-brown
marked this pull request as ready for review
July 29, 2026 10:56
0xadam-brown
requested review from
adinauer,
markushi,
romtsn and
runningcode
as code owners
July 29, 2026 10:56
Contributor
Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 6b019b7 | 319.84 ms | 333.15 ms | 13.31 ms |
| c3ee041 | 310.64 ms | 361.90 ms | 51.26 ms |
| d501a7e | 348.06 ms | 431.42 ms | 83.36 ms |
| 3998a95 | 415.94 ms | 478.54 ms | 62.60 ms |
| ed33deb | 343.30 ms | 362.41 ms | 19.10 ms |
| 5b1a06b | 310.56 ms | 362.79 ms | 52.22 ms |
| 91bb874 | 310.68 ms | 359.24 ms | 48.56 ms |
| 0ee65e9 | 317.37 ms | 366.50 ms | 49.13 ms |
| 6edfca2 | 305.52 ms | 432.78 ms | 127.26 ms |
| 5e269de | 292.83 ms | 379.12 ms | 86.29 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 6b019b7 | 0 B | 0 B | 0 B |
| c3ee041 | 0 B | 0 B | 0 B |
| d501a7e | 0 B | 0 B | 0 B |
| 3998a95 | 1.58 MiB | 2.10 MiB | 532.96 KiB |
| ed33deb | 1.58 MiB | 2.13 MiB | 559.52 KiB |
| 5b1a06b | 0 B | 0 B | 0 B |
| 91bb874 | 1.58 MiB | 2.13 MiB | 559.07 KiB |
| 0ee65e9 | 0 B | 0 B | 0 B |
| 6edfca2 | 1.58 MiB | 2.13 MiB | 559.07 KiB |
| 5e269de | 0 B | 0 B | 0 B |
markushi
approved these changes
Jul 29, 2026
Co-authored-by: Markus Hintersteiner <markus.hintersteiner@sentry.io>
0xadam-brown
enabled auto-merge (squash)
July 29, 2026 14:33
This was referenced Jul 29, 2026
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.
📜 Description
Prior to this PR, we'd always (rightly) bind originating process Proguard IDs to ANR events, but we'd (wrongly) bind current Proguard ID to ANR profile chunks. Usually the originating Proguard ID == the current Proguard ID, and so the discrepancy didn't matter. But the two differ in the situation when a user updates the host app after the ANR occurs but before it's reported. When that happens, deobfuscation for ANR profile chunks in the Sentry UI can break.
This PR ensures both the ANR event and the ANR profile chunk receive the same originating Proguard ID by:
💡 Motivation and Context
(Sorry for the wall of text ahead, but it's worth a quick read! Yours truly wrote it to make sure my LLM's approach was sane, so it should be easy to follow. It lays out the problem in detail and our possible options – including closing this PR and living with the edge case.)
Background
We report ANRs from app processs launched after each ANR occurs. Usually the same app installation is used with both processes and so the Proguard ID used to deobfuscate stack traces is the same for each. But not always! A user could have installed a new version of the app in between, so we need to make sure we grab the Proguard ID associated with the original process.
Nicely, logic to do that already exists in ApplicationExitInfoEventProcessor (link). Not so nicely, the Proguard ID produced by that logic isn't used by the profile chunk we associate with the ANR event – or at least it wasn't prior to this PR. (The profile chunk would always use the Proguard ID for the current process.)
The upshot is that app owners would see properly deobfuscated stack traces for the ANR event but possibly broken / still-obfuscated stack traces for the profile chunk in the rare case that someone installs a new version of the host app before the ANR can be reported out.
So what's going on?
ANRs are composites of two separate entities: an ANR event proper and an ANR profile chunk. That distinction goes all the way down, as the Sentry UI displays ANR events and profile chunks in different dashboards. Each entity owns a DebugMeta instance, which is the data structure used to associate a Proguard ID with the entity it belongs to.
In the SDK, the ApplicationExitInfoEventProcessor owns the pipeline for constructing both the ANR event and its profile chunk. It goes like this:
Step (2) receives the DebugMeta instance with the correct Proguard ID from ApplicationExitInfoEventProcessor. But our profile chunk processing ignores it and instead selects the Proguard ID from the current process. That’s because ApplicationExitInfoEventProcessor delegates to the existing profile chunk pipeline used for non-ANR profiles, and non-ANR profiles are always concerned with the current app process. (Note that the profile chunk pipeline is shared by the Java. Ideally that’d mean it’s Android-agnostic, but that isn’t quite the case atm, eg, it knows about Proguard IDs.)
What should we do?
Possible approaches:
[A] Introduce the concept of “originating process" into our profile chunk pipeline.
[B] Update the profile chunk API to accept a pre-selected Proguard ID (whether directly as a string param, via a Context/Hint-esque parameter, or by lookup).
[C] Include the originating Proguard ID inside the chunk already passed to our profile chunk pipeline by ApplicationExitInfoEventProcessor + update DebugMeta.builder(incomingAnrDebugMeta, …) so that it honors that ID rather than clobbering it.
[D] Do nothing / close this PR and live with the edge case of potentially (but not inevitably) broken or misleading ANR profile chunk stack traces.
The path I chose
This PR implements [C].
Approach [A] sounded best in the abstract, but it’d be a big lift as a number of the inputs ApplicationExitInfoEventProcessor relies on to decide which Proguard ID to use are either Android-specific or aren’t currently available to our profile chunk pipeline. Option [B] was a more explicit version of [C] but at the cost of modifying the public API in ways that are, at best, debatable.
Option [D] is legit, esp if you look at this PR and think the fix is more of a maintenance burden than it’s worth. (Chime in if you do!)
Addresses: JAVA-549
💚 How did you test it?
Unit tests.
📝 Checklist
sendDefaultPIIis enabled.🔮 Next steps