Add app-hang tracking via NDK game-thread heartbeat on Android - #1497
Conversation
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.
|
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.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ 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.
| // 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. |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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.
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.

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- forwardsenableNdkAppHangTracking/ndkAppHangTimeoutMillisto the Java layer, gated onEnableHangTracking && UseNativeHangTracking. Pumpssentry_app_hang_heartbeat()fromFCoreDelegates::OnEndFrame(game thread latches itself as the monitored thread), resolving the symbol lazily viadlopen("libsentry.so", RTLD_NOLOAD)+dlsymagainst the library already loaded by the Java SDK.IsNativeHangTrackingEnabled()now reflects the feature;IsHangTrackingSupported()stays false so the engineFThreadHeartBeatwatcher is never created on Android.SentryBridgeJava- appliessetEnableNdkAppHangTracking/setNdkAppHangTimeoutIntervalMillisonSentryAndroidOptions.SentrySettings- reuses the existing hang-tracking settings (no new options); updated theUseNativeHangTrackingtooltip to note Android coverage.Documentation
Related items
Nativebackend on Windows, Linux, and Mac #1427