Skip to content

Add app-hang tracking via NDK game-thread heartbeat on Android - #1497

Merged
tustanivsky merged 4 commits into
mainfrom
feat/android-heartbeat
Jul 24, 2026
Merged

Add app-hang tracking via NDK game-thread heartbeat on Android#1497
tustanivsky merged 4 commits into
mainfrom
feat/android-heartbeat

Conversation

@tustanivsky

@tustanivsky tustanivsky commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

This PR adds app-hang detection on Android that monitors the Unreal game thread. Until now, Android only had the JVM ANR watchdog (enableAnrTracking), which watches the Android main/UI looper - a different thread from Unreal's game thread. A frozen game loop while the UI thread keeps pumping went undetected. This wires up sentry-native's in-process app-hang watchdog on Android (exposed to hybrid SDKs via getsentry/sentry-java#5623), giving the same game-thread hang detection that is already available on Windows/macOS/Linux - with a native stack trace and consistent event shape across platforms.

The JVM ANR watchdog and the new NDK app-hang watchdog both stay active: they watch different threads and catch different failure modes (system ANR vs. frozen game loop).

Key Changes

  • AndroidSentrySubsystem - forwards enableNdkAppHangTracking / ndkAppHangTimeoutMillis to the Java layer, gated on EnableHangTracking && UseNativeHangTracking. Pumps sentry_app_hang_heartbeat() from FCoreDelegates::OnEndFrame (game thread latches itself as the monitored thread), resolving the symbol lazily via dlopen("libsentry.so", RTLD_NOLOAD) + dlsym against the library already loaded by the Java SDK. IsNativeHangTrackingEnabled() now reflects the feature; IsHangTrackingSupported() stays false so the engine FThreadHeartBeat watcher is never created on Android.
  • SentryBridgeJava - applies setEnableNdkAppHangTracking / setNdkAppHangTimeoutIntervalMillis on SentryAndroidOptions.
  • SentrySettings - reuses the existing hang-tracking settings (no new options); updated the UseNativeHangTracking tooltip to note Android coverage.

Documentation

Related items

Enable sentry-native's app-hang watchdog on Android by pumping sentry_app_hang_heartbeat() from OnEndFrame (game thread) and forwarding the NDK app-hang options through sentry-java. Monitors the UE game thread, mirroring the desktop native hang-tracking path, and runs alongside the existing JVM ANR watchdog (which watches the Android UI looper). Reuses the EnableHangTracking / UseNativeHangTracking / HangTimeoutDuration settings.
@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 3aba879

Give the SDK a moment before Close() so the sentry-native app-hang envelope is uploaded from the outbox in-session, matching the message/log/metric/tracing integration tests. Verified on device: a single hang-capture run drains the outbox.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

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 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 3aba879. Configure here.

Comment thread plugin-dev/Source/Sentry/Private/Android/AndroidSentrySubsystem.cpp
Comment on lines +556 to +557
// libsentry.so is loaded asynchronously by the Java SDK (io.sentry.ndk.SentryNdk), so resolve
// the symbol lazily against the already-loaded library rather than linking it at build time.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this mean that it can take several frames on startup until it succeeds to resolve the symbol? does it have any measurable impact on the startup frames?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In practice it resolves on the very first frame, so no. The OnEndFrame listener is only registered after the Android SDK initialization completes and that initialization waits for the NDK library to finish loading.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the silly questions, but do we have any mechanism for delaying app hang tracking startup? Some games might want to start it only after level loading and other startup work is complete...

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

App hang tracking starts with the first heartbeat so technically we could expose a setting to control whether it happens automatically after init along with an API to trigger it manually later.

It'd probably also be useful to support pausing and resuming hang tracking since level loading (or other long-running operations) can happen multiple times during a game session.

cc @bitsandfoxes

@tustanivsky
tustanivsky merged commit 3d457f2 into main Jul 24, 2026
98 of 100 checks passed
@tustanivsky
tustanivsky deleted the feat/android-heartbeat branch July 24, 2026 16:04
tustanivsky added a commit to getsentry/sentry-docs that referenced this pull request Jul 24, 2026
Updates the Unreal **App Hangs** page to reflect that the SDK now
supports the sentry-native app-hang watchdog on Android via the NDK
integration.

### Changes
- Native watchdog availability now lists **Android** (routed through the
NDK integration), monitoring the game thread.
- Notes that on Android it runs **alongside** the Java SDK's ANR
detection (which watches the Android main/UI thread), so a freeze
affecting both threads can be reported as both a hang event and an ANR.
- Adds an Android note under **Native App Hang Detection** and a
corresponding **Limitations** entry.

### Related
Documents the feature added in getsentry/sentry-unreal#1497.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants