-
-
Notifications
You must be signed in to change notification settings - Fork 465
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 <noreply@anthropic.com>
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 |
|---|---|---|---|
| 3d205d0 | 352.15 ms | 432.53 ms | 80.38 ms |
| fc5ccaf | 256.80 ms | 322.36 ms | 65.56 ms |
| ee747ae | 374.71 ms | 455.18 ms | 80.47 ms |
| 6edfca2 | 314.02 ms | 383.20 ms | 69.18 ms |
| 674d437 | 355.28 ms | 504.18 ms | 148.90 ms |
| 6405ec5 | 310.88 ms | 354.56 ms | 43.69 ms |
| bbc35bb | 324.88 ms | 425.73 ms | 100.85 ms |
| dba088c | 321.78 ms | 364.59 ms | 42.82 ms |
| fc5ccaf | 279.11 ms | 353.34 ms | 74.23 ms |
| 3699cd5 | 423.60 ms | 495.52 ms | 71.92 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 3d205d0 | 1.58 MiB | 2.10 MiB | 532.97 KiB |
| fc5ccaf | 1.58 MiB | 2.13 MiB | 557.54 KiB |
| ee747ae | 1.58 MiB | 2.10 MiB | 530.95 KiB |
| 6edfca2 | 1.58 MiB | 2.13 MiB | 559.07 KiB |
| 674d437 | 1.58 MiB | 2.10 MiB | 530.94 KiB |
| 6405ec5 | 1.58 MiB | 2.12 MiB | 552.23 KiB |
| bbc35bb | 1.58 MiB | 2.12 MiB | 553.01 KiB |
| dba088c | 1.58 MiB | 2.13 MiB | 558.99 KiB |
| fc5ccaf | 1.58 MiB | 2.13 MiB | 557.54 KiB |
| 3699cd5 | 1.58 MiB | 2.10 MiB | 533.45 KiB |
Previous results on branch: markushi/feat/anr-profiling
Startup times
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| be4960b | 322.67 ms | 380.85 ms | 58.18 ms |
| 184b846 | 276.09 ms | 351.65 ms | 75.56 ms |
| b238cff | 332.00 ms | 401.47 ms | 69.47 ms |
| c22421f | 331.24 ms | 367.91 ms | 36.67 ms |
| a4af52f | 304.52 ms | 364.92 ms | 60.40 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| be4960b | 1.58 MiB | 2.13 MiB | 562.64 KiB |
| 184b846 | 1.58 MiB | 2.13 MiB | 558.70 KiB |
| b238cff | 1.58 MiB | 2.13 MiB | 562.66 KiB |
| c22421f | 1.58 MiB | 2.13 MiB | 563.53 KiB |
| a4af52f | 1.58 MiB | 2.13 MiB | 563.53 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
sentry-android-core/src/main/java/io/sentry/android/core/anr/AnrStackTrace.java
Outdated
Show resolved
Hide resolved
sentry-android-core/src/main/java/io/sentry/android/core/anr/AnrProfilingIntegration.java
Show resolved
Hide resolved
|
@sentry review |
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
Outdated
Show resolved
Hide resolved
sentry-android-core/src/main/java/io/sentry/android/core/AnrV2Integration.java
Show resolved
Hide resolved
markushi
left a comment
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.
Addressing bot comments:
Concurrent QueueFile Access (Comments on AnrV2Integration.java:327, :367):
✅ Working as designed. The reader uses AnrProfileRotationHelper.getLastFile() which reads from a rotated/archived file, while the writer writes to the current file. They access different files.
AnrProfileManager file descriptor leak (AnrProfileManager.java:50):
✅ Already fixed. The code uses try-with-resources: try (final AnrProfileManager provider = new AnrProfileManager(options, lastFile))
lowQualityPackages initialization (AnrCulpritIdentifier.java:85):
✅ Already fixed. The field uses a static initializer block.
Stack depth calculation (AggregatedStackTrace.java:38):
✅ Already fixed.
Incomplete stack trace handling (AnrCulpritIdentifier.java:138):
✅ Already fixed. Code has if (stackTraceMap.isEmpty()) return null; guard at line 140.
Empty debug log (AnrV2Integration.java:346):
✅ Already fixed.
Missing rotate() call (AnrV2Integration.java:424):
✅ Working as designed. Rotation should only happen once after app start, not on every ANR event read.
Stack trace serialization (AnrStackTrace.java:35):
✅ Already fixed.
Missing listener removal (AnrProfilingIntegration.java:79):
✅ Already fixed.
Profile ID mismatch (AnrV2Integration.java:418):
✅ Working as designed. We intentionally return chunk.getProfilerId() to reference the chunk_id as profiler_id.
hasOnlySystemFrames() fingerprinting (AnrV2Integration.java:321, :497):
✅ FIXED in this update. Modified to return false when exceptions list is null/empty, preventing incorrect fingerprinting when profiling fails.
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.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| final @NotNull SentryOptions opts = | ||
| Objects.requireNonNull(options, "Options can't be null"); | ||
| final @NotNull File currentFile = | ||
| AnrProfileRotationHelper.getFileForRecording(new File(opts.getCacheDirPath())); |
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.
Missing null check for cacheDirPath causes NPE
Medium Severity
When opts.getCacheDirPath() returns null, new File(null) throws a NullPointerException. Unlike AnrV2Integration which checks for null cacheDirPath before using it (line 94 and 236), AnrProfilingIntegration has no such validation. If ANR profiling is enabled but cacheDirPath is null, the integration will register itself as a listener, and upon the first ANR suspicion, calling clearStacks() or addStackTrace() will crash.
|
|
||
| if (this.options == null) { | ||
| return; | ||
| } |
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.
Dead code due to requireNonNull throwing before null check
Low Severity
The if (this.options == null) return; check is unreachable dead code. Objects.requireNonNull on line 51-54 throws an IllegalArgumentException when the ternary expression evaluates to null (i.e., when options is not a SentryAndroidOptions). The null check can never execute because the exception is thrown first.
| if (!AnrProfileRotationHelper.deleteLastFile(cacheDir)) { | ||
| options.getLogger().log(SentryLevel.INFO, "Could not delete ANR profile file"); | ||
| } | ||
| } |
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.
Profile file deleted prematurely when reporting historical ANRs
Medium Severity
The ANR profile file is deleted in a finally block on every call to applyAnrProfile, regardless of whether the profile was actually matched and used. When reportHistoricalAnrs is enabled, historical ANRs are processed before the latest ANR. Each historical ANR triggers applyAnrProfile, which deletes the profile file even though the timestamp doesn't match. By the time the latest ANR (which should match the profile) is processed, the file is already deleted and the profile is lost.


📜 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 eventsAnrV2Integrationnow takes care of matching and capturing the profile on the next start💡 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