Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

### Features

- Added `AndroidNativeAnrEnabled` (default `true`) to enable ANR detection through `sentry-java` SDK. The native ANR integration monitors the Android UI thread. On API ≥ 30 this uses [ANR v2](https://docs.sentry.io/platforms/android/configuration/app-not-respond/) via `ApplicationExitInfo` to report OS-detected ANRs from prior runs; on API < 30 it falls back to an in-process watchdog. This is complementary to the Unity SDK's C# watchdog, which monitors the Unity player loop. ([#2671](https://github.com/getsentry/sentry-unity/pull/2671))
- Added `EnableAppHangTracking` (default `true`) to enable app hang (ANR) detection through the `sentry-cocoa` SDK on iOS and macOS. When enabled, sentry-cocoa monitors the main thread and replaces the Unity SDK's C# watchdog on these platforms, allowing Sentry to show a stack trace for the hang event ([#2679](https://github.com/getsentry/sentry-unity/pull/2679))
- Added `AndroidNativeAnrEnabled` (default `true`) to enable ANR detection through the `sentry-java` SDK. The native ANR integration monitors the Android UI thread. On API ≥ 30 this uses [ANR v2](https://docs.sentry.io/platforms/android/configuration/app-not-respond/) via `ApplicationExitInfo` to report OS-detected ANRs from prior runs; on API < 30 it falls back to an in-process watchdog. This is complementary to the Unity SDK's C# watchdog, which monitors the Unity player loop. ([#2671](https://github.com/getsentry/sentry-unity/pull/2671))

### Dependencies

Expand Down
3 changes: 2 additions & 1 deletion src/Sentry.Unity.Editor.iOS/NativeOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ internal static string Generate(SentryUnityOptions options)
@""maxBreadcrumbs"": @{options.MaxBreadcrumbs},
@""maxCacheItems"": @{options.MaxCacheItems},
@""enableAutoSessionTracking"": @NO,
@""enableAppHangTracking"": @NO,
@""enableAppHangTracking"": @{ToObjCString(options.EnableAppHangTracking)},
@""appHangTimeoutInterval"": @{options.AnrTimeout.TotalSeconds.ToString(System.Globalization.CultureInfo.InvariantCulture)},
@""enableCaptureFailedRequests"": @{ToObjCString(options.CaptureFailedRequests)},
@""failedRequestStatusCodes"" : @[{failedRequestStatusCodesArray}],
@""sendDefaultPii"" : @{ToObjCString(options.SendDefaultPii)},
Expand Down
19 changes: 11 additions & 8 deletions src/Sentry.Unity.Editor/ConfigurationWindow/AdvancedTab.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,24 @@ internal static void Display(ScriptableSentryUnityOptions options, SentryCliOpti
EditorGUILayout.Space();

{
options.AnrDetectionEnabled = EditorGUILayout.BeginToggleGroup(
new GUIContent("ANR Detection", "Whether the SDK should report 'Application Not " +
"Responding' events."),
options.AnrDetectionEnabled = EditorGUILayout.Toggle(
new GUIContent("C# Watchdog", "Whether the SDK should run the C# main-thread watchdog " +
"to report 'Application Not Responding' events."),
options.AnrDetectionEnabled);
EditorGUI.indentLevel++;

options.EnableAppHangTracking = EditorGUILayout.Toggle(
new GUIContent("App Hang Tracking",
"Enables app hang (ANR) detection via the native SDK. " +
"When enabled, the native SDK monitors the main thread and the Unity SDK's C# ANR " +
"watchdog is skipped to avoid duplicate reports."),
options.EnableAppHangTracking);

options.AnrTimeout = EditorGUILayout.IntField(
new GUIContent("Timeout [ms]",
new GUIContent("App Hang Timeout [ms]",
"The duration in [ms] for how long the game has to be unresponsive " +
"before an ANR event is reported.\nDefault: 5000ms"),
options.AnrTimeout);
options.AnrTimeout = Math.Max(0, options.AnrTimeout);

EditorGUI.indentLevel--;
EditorGUILayout.EndToggleGroup();
}

EditorGUILayout.Space();
Expand Down
9 changes: 9 additions & 0 deletions src/Sentry.Unity.iOS/SentryCocoaBridgeProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ public static bool Init(SentryUnityOptions options)
// See https://github.com/getsentry/sentry-unity/issues/1658
OptionsSetInt(cOptions, "enableNetworkBreadcrumbs", 0);

Logger?.LogDebug("Setting EnableAppHangTracking: {0}", options.EnableAppHangTracking);
OptionsSetInt(cOptions, "enableAppHangTracking", options.EnableAppHangTracking ? 1 : 0);

Logger?.LogDebug("Setting AppHangTimeoutInterval: {0}s", options.AnrTimeout.TotalSeconds);
OptionsSetDouble(cOptions, "appHangTimeoutInterval", options.AnrTimeout.TotalSeconds);
Comment thread
bitsandfoxes marked this conversation as resolved.
Outdated

Logger?.LogDebug("Setting EnableWatchdogTerminationTracking: {0}", options.IosWatchdogTerminationIntegrationEnabled);
OptionsSetInt(cOptions, "enableWatchdogTerminationTracking", options.IosWatchdogTerminationIntegrationEnabled ? 1 : 0);

Expand Down Expand Up @@ -103,6 +109,9 @@ public static bool Init(SentryUnityOptions options)
[DllImport("__Internal", EntryPoint = "SentryNativeBridgeOptionsSetInt")]
private static extern void OptionsSetInt(IntPtr options, string name, int value);

[DllImport("__Internal", EntryPoint = "SentryNativeBridgeOptionsSetDouble")]
private static extern void OptionsSetDouble(IntPtr options, string name, double value);
Comment thread
bitsandfoxes marked this conversation as resolved.
Comment thread
cursor[bot] marked this conversation as resolved.

[DllImport("__Internal", EntryPoint = "SentryNativeBridgeOptionsAddFailedRequestStatusCodeRange")]
private static extern void OptionsAddFailedRequestStatusCodeRange(IntPtr options, int min, int max);

Expand Down
6 changes: 6 additions & 0 deletions src/Sentry.Unity.iOS/SentryNativeCocoa.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ internal static void Configure(SentryUnityOptions options, RuntimePlatform platf
options.ScopeObserver = new NativeScopeObserver("macOS", options);
}

if (options.EnableAppHangTracking)
{
Logger?.LogDebug("Disabling the C# ANR watchdog - sentry-cocoa handles app hang detection.");
options.DisableAnrIntegration();
}
Comment thread
bitsandfoxes marked this conversation as resolved.
Outdated

SentryCocoaBridgeProxy.SetSdkName(); // Since we're not building the SDK we have to overwrite the name here

options.NativeContextWriter = new NativeContextWriter();
Expand Down
2 changes: 2 additions & 0 deletions src/Sentry.Unity/ScriptableSentryUnityOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public static string GetConfigPath(string? notDefaultConfigName = null)

[field: SerializeField] public bool AnrDetectionEnabled { get; set; } = true;
[field: SerializeField] public int AnrTimeout { get; set; } = (int)TimeSpan.FromSeconds(5).TotalMilliseconds;
[field: SerializeField] public bool EnableAppHangTracking { get; set; } = true;

[field: SerializeField] public bool CaptureFailedRequests { get; set; } = true;

Expand Down Expand Up @@ -201,6 +202,7 @@ internal SentryUnityOptions ToSentryUnityOptions(
DiagnosticLevel = DiagnosticLevel,
CaptureLogErrorEvents = CaptureLogErrorEvents,
AnrTimeout = TimeSpan.FromMilliseconds(AnrTimeout),
EnableAppHangTracking = EnableAppHangTracking,
CaptureFailedRequests = CaptureFailedRequests,
FilterBadGatewayExceptions = FilterBadGatewayExceptions,
IosNativeSupportEnabled = IosNativeSupportEnabled,
Expand Down
12 changes: 12 additions & 0 deletions src/Sentry.Unity/SentryUnityOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,18 @@ public sealed class SentryUnityOptions : SentryOptions
/// </summary>
public bool IosWatchdogTerminationIntegrationEnabled { get; set; } = false;

/// <summary>
/// Enables app hang (ANR) detection on iOS and macOS through the native (sentry-cocoa) SDK.
/// When enabled, sentry-cocoa monitors the main thread for hangs and the Unity SDK's
/// C# ANR watchdog is skipped to avoid duplicate reports.
/// </summary>
/// <remarks>
/// sentry-cocoa observes the platform run loop directly, which yields more accurate
/// app-hang detection than the Unity-side watchdog. Disable this only if you want
/// to fall back to the C# watchdog.
/// </remarks>
public bool EnableAppHangTracking { get; set; } = true;

/// <summary>
/// Whether the SDK should initialize the native SDK before the game starts. This bakes the options at build-time into
/// the generated Xcode project. Modifying the options at runtime will not affect the options used to initialize
Expand Down
40 changes: 40 additions & 0 deletions test/Sentry.Unity.Editor.iOS.Tests/NativeOptionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,46 @@ public void CreateOptionsFile_NewSentryOptions_ContainsSdkNameSetting()
File.Delete(testOptionsFileName);
}

[Test]
public void CreateOptionsFile_EnableAppHangTracking_SetsYes()
{
const string testOptionsFileName = "testOptions.m";

NativeOptions.CreateFile(testOptionsFileName, new SentryUnityOptions { EnableAppHangTracking = true });

var nativeOptions = File.ReadAllText(testOptionsFileName);
StringAssert.Contains("@\"enableAppHangTracking\": @YES", nativeOptions);

File.Delete(testOptionsFileName);
}

[Test]
public void CreateOptionsFile_AppHangTrackingDisabled_SetsNo()
{
const string testOptionsFileName = "testOptions.m";

NativeOptions.CreateFile(testOptionsFileName, new SentryUnityOptions { EnableAppHangTracking = false });

var nativeOptions = File.ReadAllText(testOptionsFileName);
StringAssert.Contains("@\"enableAppHangTracking\": @NO", nativeOptions);

File.Delete(testOptionsFileName);
}

[Test]
public void CreateOptionsFile_AnrTimeout_WrittenAsSeconds()
{
const string testOptionsFileName = "testOptions.m";

NativeOptions.CreateFile(testOptionsFileName,
new SentryUnityOptions { AnrTimeout = System.TimeSpan.FromMilliseconds(7500) });

var nativeOptions = File.ReadAllText(testOptionsFileName);
StringAssert.Contains("@\"appHangTimeoutInterval\": @7.5", nativeOptions);

File.Delete(testOptionsFileName);
}

[Test]
public void CreateOptionsFile_FilterBadGatewayEnabled_AddsFiltering()
{
Expand Down
Loading