-
-
Notifications
You must be signed in to change notification settings - Fork 463
feat(anr): Profile main thread when ANR and report ANR profiles to Sentry #4899
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
sentry-android-core/src/main/java/io/sentry/android/core/AnrV2Integration.java
Outdated
Show resolved
Hide resolved
sentry-android-core/src/main/java/io/sentry/android/core/anr/AnrProfileManager.java
Show resolved
Hide resolved
sentry-android-core/src/main/java/io/sentry/android/core/anr/AnrCulpritIdentifier.java
Show resolved
Hide resolved
sentry-android-core/src/main/java/io/sentry/android/core/anr/AggregatedStackTrace.java
Outdated
Show resolved
Hide resolved
Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| f634d01 | 359.58 ms | 433.88 ms | 74.30 ms |
| 9fbb112 | 401.87 ms | 515.87 ms | 114.00 ms |
| d5a29b6 | 298.62 ms | 391.78 ms | 93.16 ms |
| bbc35bb | 298.53 ms | 372.17 ms | 73.64 ms |
| b3d8889 | 420.46 ms | 453.71 ms | 33.26 ms |
| a5ab36f | 320.47 ms | 389.77 ms | 69.30 ms |
| ee747ae | 405.43 ms | 485.70 ms | 80.28 ms |
| 951caf7 | 323.66 ms | 392.82 ms | 69.16 ms |
| b6702b0 | 395.86 ms | 409.98 ms | 14.12 ms |
| 27d7cf8 | 369.82 ms | 422.62 ms | 52.80 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| f634d01 | 1.58 MiB | 2.10 MiB | 533.40 KiB |
| 9fbb112 | 1.58 MiB | 2.11 MiB | 539.18 KiB |
| d5a29b6 | 1.58 MiB | 2.12 MiB | 549.37 KiB |
| bbc35bb | 1.58 MiB | 2.12 MiB | 553.01 KiB |
| b3d8889 | 1.58 MiB | 2.10 MiB | 535.07 KiB |
| a5ab36f | 1.58 MiB | 2.12 MiB | 555.26 KiB |
| ee747ae | 1.58 MiB | 2.10 MiB | 530.95 KiB |
| 951caf7 | 1.58 MiB | 2.13 MiB | 558.77 KiB |
| b6702b0 | 1.58 MiB | 2.12 MiB | 551.79 KiB |
| 27d7cf8 | 1.58 MiB | 2.12 MiB | 549.42 KiB |
sentry-android-core/src/main/java/io/sentry/android/core/anr/AnrCulpritIdentifier.java
Show resolved
Hide resolved
…ntry-java into markushi/feat/anr-profiling
sentry-android-core/src/main/java/io/sentry/android/core/AnrV2Integration.java
Outdated
Show resolved
Hide resolved
sentry-android-core/src/main/java/io/sentry/android/core/AnrV2Integration.java
Show resolved
Hide resolved
sentry-android-core/src/main/java/io/sentry/android/core/AnrV2Integration.java
Show resolved
Hide resolved
| for (final @NotNull StackTraceElement element : stack) { | ||
| dos.writeUTF(StringUtils.getOrEmpty(element.getClassName())); | ||
| dos.writeUTF(StringUtils.getOrEmpty(element.getMethodName())); | ||
| dos.writeUTF(StringUtils.getOrEmpty(element.getFileName())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Stack trace file name serialization loses null distinction
When serializing stack trace elements, StringUtils.getOrEmpty(element.getFileName()) converts null file names to empty strings. After deserialization, these become actual empty strings instead of null. In StackTraceConverter.createFrameSignature(), Java string concatenation produces different results for null vs "" - a null file name produces "Class#method#null#10" while an empty string produces "Class#method##10". This causes the frame deduplication logic to treat identical frames (especially native methods which have null file names) as different after a round-trip through persistence, resulting in duplicate frames in the profile.
Additional Locations (1)
| p.close(); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Missing listener removal in close method
The close() method registers itself as an AppStateListener via addAppStateListener(this) in register() but never calls AppState.getInstance().removeAppStateListener(this) when closing. Other integrations in the codebase that implement AppStateListener (like SystemEventsBreadcrumbsIntegration and AndroidConnectionStatusProvider) consistently remove themselves in their close() methods. This omission causes the integration object to remain referenced in the listener list after closure, creating a minor resource leak where the closed integration continues receiving (and ignoring) lifecycle callbacks.
📜 Description
Adds ANR (Application Not Responding) profiling integration that profiles the main thread when an ANR is detected and reports the captured profiles to Sentry.
Key Changes:
AnrProfilingIntegrationto capture profiles during ANR eventsAnrProfileManagerto manage ANR profile lifecycleAnrCulpritIdentifierto identify the culprit code causing ANR💡 Motivation and Context
This feature enables better ANR diagnostics by capturing profiling data at the time of ANR detection, allowing developers to identify performance bottlenecks and problematic code paths causing application hangs.
💚 How did you test it?
📝 Checklist
sendDefaultPIIis enabled.🔮 Next steps