Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@

### Behavioural Changes and Deprecations

- The C# ANR watchdog and its configuration options (`AnrDetectionEnabled`, `AnrTimeout`, and `DisableAnrIntegration`) are now marked as `[Obsolete]` and `false` by default. Use `Experimental.EnableNativeAppHangTracking` instead. ([#2784](https://github.com/getsentry/sentry-unity/pull/2784))
- The C# ANR watchdog and its configuration options (`AnrDetectionEnabled`, `AnrTimeout`, and `DisableAnrIntegration`) are now marked as `[Obsolete]` and `false` by default. Use experimental `EnableAppHangTracking` instead. ([#2784](https://github.com/getsentry/sentry-unity/pull/2784), [#2787](https://github.com/getsentry/sentry-unity/pull/2787))
- `EnableAppHangTracking` now controls native app-hang tracking on Android, iOS, Linux, macOS, and Windows and defaults to `false`. `Experimental.EnableNativeAppHangTracking` is deprecated.

### Features

- Extended experimental `options.Experimental.EnableNativeAppHangTracking` to Android. It now configures the Android NDK app-hang detector and emits Unity main-thread heartbeats. This option requires `NdkIntegrationEnabled` to be set to `true` ([#2778](https://github.com/getsentry/sentry-unity/pull/2778))
- Extended experimental `EnableAppHangTracking` to Android. It configures the Android NDK app-hang detector and emits Unity main-thread heartbeats. This requires `NdkIntegrationEnabled` to be set to `true` ([#2778](https://github.com/getsentry/sentry-unity/pull/2778))

### Fixes

Expand Down
3 changes: 2 additions & 1 deletion docs/agent-guides/platform-apple.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
## Cocoa Behavior

- Cocoa configuration initializes bridge, scope/context sync, SDK name, crashed-last-run, and IL2CPP installation ID.
- iOS native app-hang tracking can disable C# ANR watchdog.
- `EnableAppHangTracking` configures Cocoa app-hang tracking on iOS and macOS when the Cocoa backend is active.
- App-hang tracking disables the C# ANR watchdog on iOS and macOS when the Cocoa backend is active.
- macOS Cocoa screenshots are disabled because UIKit is unavailable.
- Cocoa attachment synchronization is not implemented.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ MonoBehaviour:
<MacosBackend>k__BackingField: 0
<WindowsBackend>k__BackingField: 0
<LinuxBackend>k__BackingField: 0
<EnableNativeAppHangTracking>k__BackingField: 0
<EnableNativeAppHangTracking>k__BackingField: 1
<OptionsConfiguration>k__BackingField: {fileID: 11400000, guid: cea63afb7c75f429799422326f926abe, type: 2}
<Debug>k__BackingField: 1
<DebugOnlyInEditor>k__BackingField: 0
Expand Down
2 changes: 1 addition & 1 deletion src/Sentry.Unity.Android/SentryJava.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public void Init(SentryUnityOptions options)
androidOptions.Call("setEnableScopePersistence", options.AndroidNativeAnrEnabled);
androidOptions.Call("setReportHistoricalAnrs", options.AndroidReportHistoricalAnrs);
androidOptions.Call("setAttachAnrThreadDump", options.AndroidAttachAnrThreadDump);
androidOptions.Call("setEnableNdkAppHangTracking", options.Experimental.EnableNativeAppHangTracking);
androidOptions.Call("setEnableNdkAppHangTracking", options.NativeAppHangTrackingEnabled);
androidOptions.Call("setNdkAppHangTimeoutIntervalMillis", (long)Math.Max(0, options.AppHangTimeout.TotalMilliseconds));

androidOptions.Call("setTombstoneEnabled", options.AndroidTombstoneEnabled);
Expand Down
2 changes: 1 addition & 1 deletion src/Sentry.Unity.Android/SentryNativeAndroid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public static void Configure(SentryUnityOptions options)
options.EnableScopeSync = true;
options.NativeDebugImageProvider = new Native.NativeDebugImageProvider();

if (options.Experimental.EnableNativeAppHangTracking && options.NdkIntegrationEnabled)
if (options.NativeAppHangTrackingEnabled && options.NdkIntegrationEnabled)
{
Logger?.LogDebug("Starting the app-hang heartbeat coroutine.");
SentryMonoBehaviour.Instance.StartAppHangHeartbeat(SentryNative.AppHangHeartbeat);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ internal void ModifyManifest(string basePath)
androidManifest.SetAnr(_options.AndroidNativeAnrEnabled);
androidManifest.SetPersistentScopeObserver(_options.AndroidNativeAnrEnabled);
androidManifest.SetAttachAnrThreadDump(_options.AndroidAttachAnrThreadDump);
androidManifest.SetNdkAppHangTracking(_options.Experimental.EnableNativeAppHangTracking);
androidManifest.SetNdkAppHangTracking(_options.NativeAppHangTrackingEnabled);
androidManifest.SetNdkAppHangTimeout((long)Math.Max(0, _options.AppHangTimeout.TotalMilliseconds));
androidManifest.SetTombstone(_options.AndroidTombstoneEnabled);
androidManifest.SetTombstoneReportHistorical(_options.AndroidReportHistoricalTombstones);
Expand Down
16 changes: 5 additions & 11 deletions src/Sentry.Unity.Editor/ConfigurationWindow/AdvancedTab.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ internal static void Display(ScriptableSentryUnityOptions options, SentryCliOpti
{
GUILayout.Label("C# Watchdog (Deprecated)", EditorStyles.boldLabel);
EditorGUILayout.HelpBox(
"The C# ANR watchdog is deprecated. Use Experimental.EnableNativeAppHangTracking instead. " +
"The C# ANR watchdog is deprecated. Use EnableAppHangTracking instead. " +
"These settings will be removed in a future version.",
MessageType.Warning);

Expand All @@ -66,12 +66,13 @@ internal static void Display(ScriptableSentryUnityOptions options, SentryCliOpti
EditorGUILayout.Space();

{
GUILayout.Label("App Hang Tracking", EditorStyles.boldLabel);
GUILayout.Label("App Hang Tracking (Experimental)", EditorStyles.boldLabel);

options.EnableAppHangTracking = EditorGUILayout.Toggle(
new GUIContent("Enable",
"Enables app hang detection on iOS via sentry-cocoa. App hang detection on Android, macOS, " +
"Windows, and Linux is experimental and controlled separately in the Experimental section."),
"Enables experimental app hang detection via sentry-cocoa on iOS and macOS with the Cocoa " +
"backend, and via sentry-native on Android and native desktop backends. Android requires NDK " +
"Integration; macOS requires the Native backend when using sentry-native."),
options.EnableAppHangTracking);

options.AppHangTimeout = EditorGUILayout.IntField(
Expand Down Expand Up @@ -278,13 +279,6 @@ internal static void Display(ScriptableSentryUnityOptions options, SentryCliOpti
options.Experimental.LinuxBackend);
}

options.Experimental.EnableNativeAppHangTracking = EditorGUILayout.Toggle(
Comment thread
bitsandfoxes marked this conversation as resolved.
new GUIContent(
"Native App Hang Tracking",
"Enables app hang detection via sentry-native on Android, macOS, Windows, and Linux. Android " +
"requires NDK Integration; macOS requires its backend above to be set to 'Native'. Shares the " +
"App Hang Timeout configured in the App Hang Tracking section. iOS is unaffected by this option."),
options.Experimental.EnableNativeAppHangTracking);
}
EditorGUI.indentLevel--;
EditorGUILayout.EndFoldoutHeaderGroup();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public override void OnInspectorGUI()
EditorGUILayout.IntField("Watchdog Timeout [ms]", options.AnrTimeout);
#pragma warning restore CS0618 // Type or member is obsolete

EditorGUILayout.LabelField("App Hang Tracking", EditorStyles.boldLabel);
EditorGUILayout.LabelField("App Hang Tracking (Experimental)", EditorStyles.boldLabel);
EditorGUILayout.Toggle("Enable", options.EnableAppHangTracking);
EditorGUILayout.IntField("App Hang Timeout [ms]", options.AppHangTimeout);

Expand Down
2 changes: 1 addition & 1 deletion src/Sentry.Unity.Native/SentryNative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ internal static void Configure(SentryUnityOptions options, RuntimePlatform platf
}
options.CrashedLastRun = () => crashedLastRun;

if (options.Experimental.EnableNativeAppHangTracking)
if (options.NativeAppHangTrackingEnabled)
{
Logger?.LogDebug("Starting the app-hang heartbeat coroutine.");
SentryMonoBehaviour.Instance.StartAppHangHeartbeat(SentryNativeBridge.AppHangHeartbeat);
Expand Down
4 changes: 2 additions & 2 deletions src/Sentry.Unity.Native/SentryNativeBridge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ is RuntimePlatform.WindowsPlayer or RuntimePlatform.WindowsServer
Logger?.LogInfo("Passing the native logs back to the C# layer is not supported on Mono - skipping native logger.");
}

Logger?.LogDebug("Setting EnableNativeAppHangTracking: {0}", options.Experimental.EnableNativeAppHangTracking);
sentry_options_set_enable_app_hang_tracking(cOptions, options.Experimental.EnableNativeAppHangTracking ? 1 : 0);
Logger?.LogDebug("Setting EnableAppHangTracking: {0}", options.NativeAppHangTrackingEnabled);
sentry_options_set_enable_app_hang_tracking(cOptions, options.NativeAppHangTrackingEnabled ? 1 : 0);

var appHangTimeoutMs = (ulong)Math.Max(0, options.AppHangTimeout.TotalMilliseconds);
Logger?.LogDebug("Setting AppHangTimeout: {0}ms", appHangTimeoutMs);
Expand Down
16 changes: 8 additions & 8 deletions src/Sentry.Unity.iOS/SentryNativeCocoa.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,6 @@ internal static void Configure(SentryUnityOptions options, RuntimePlatform platf

options.ScopeObserver = new NativeScopeObserver("iOS", options);

if (options.EnableAppHangTracking)
{
Logger?.LogDebug("Disabling the C# ANR watchdog - sentry-cocoa handles app hang detection.");
#pragma warning disable CS0618 // Type or member is obsolete
options.DisableAnrIntegration();
#pragma warning restore CS0618 // Type or member is obsolete
}

}
else
{
Expand All @@ -63,6 +55,14 @@ 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.");
#pragma warning disable CS0618 // Type or member is obsolete
options.DisableAnrIntegration();
#pragma warning restore CS0618 // Type or member is obsolete
}

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

options.NativeContextWriter = new NativeContextWriter();
Expand Down
8 changes: 3 additions & 5 deletions src/Sentry.Unity/ExperimentalSentryUnityOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,9 @@ public class ExperimentalSentryUnityOptions
[field: SerializeField] public LinuxBackend LinuxBackend { get; set; } = LinuxBackend.Breakpad;

/// <summary>
/// Enables app hang detection via <c>sentry-native</c> on Android, macOS, Windows, and Linux. Defaults to
/// <c>false</c>. On Android, requires <c>NdkIntegrationEnabled</c>. On macOS, requires the backend to be
/// switched to <see cref="Sentry.Unity.MacosBackend.Native"/>. <c>sentry-native</c> monitors the main thread and
/// produces an app hang event including a stack trace. When enabled, the C# watchdog is skipped to avoid
/// duplicate reports. The timeout is taken from <c>AppHangTimeout</c>.
/// Legacy opt-in for native app hang detection. Use <see cref="SentryUnityOptions.EnableAppHangTracking"/>
/// instead. This property will be removed in a future version.
/// </summary>
[Obsolete("Use EnableAppHangTracking instead. This property will be removed in a future version.")]
[field: SerializeField] public bool EnableNativeAppHangTracking { get; set; } = false;
}
8 changes: 5 additions & 3 deletions src/Sentry.Unity/ScriptableSentryUnityOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,13 @@ public static string GetConfigPath(string? notDefaultConfigName = null)
[field: SerializeField] public int MaxQueueItems { get; set; } = 30;

[field: SerializeField]
[Obsolete("The C# ANR watchdog is deprecated. Use Experimental.EnableNativeAppHangTracking instead. This property will be removed in a future version.")]
[Obsolete("The C# ANR watchdog is deprecated. Use EnableAppHangTracking instead. This property will be removed in a future version.")]
public bool AnrDetectionEnabled { get; set; } = false;

[field: SerializeField]
[Obsolete("The C# ANR watchdog is deprecated. Use Experimental.EnableNativeAppHangTracking instead. This property will be removed in a future version.")]
[Obsolete("The C# ANR watchdog is deprecated. Use EnableAppHangTracking instead. This property will be removed in a future version.")]
public int AnrTimeout { get; set; } = (int)TimeSpan.FromSeconds(5).TotalMilliseconds;
[field: SerializeField] public bool EnableAppHangTracking { get; set; } = true;
[field: SerializeField] public bool EnableAppHangTracking { get; set; } = false;
[field: SerializeField] public int AppHangTimeout { get; set; } = (int)TimeSpan.FromSeconds(5).TotalMilliseconds;

[field: SerializeField] public bool CaptureFailedRequests { get; set; } = true;
Expand Down Expand Up @@ -244,7 +244,9 @@ internal SentryUnityOptions ToSentryUnityOptions(
options.Experimental.MacosBackend = Experimental.MacosBackend;
options.Experimental.WindowsBackend = Experimental.WindowsBackend;
options.Experimental.LinuxBackend = Experimental.LinuxBackend;
#pragma warning disable CS0618 // Type or member is obsolete
options.Experimental.EnableNativeAppHangTracking = Experimental.EnableNativeAppHangTracking;
#pragma warning restore CS0618 // Type or member is obsolete

// By default, the cacheDirectoryPath gets set on known platforms. We're overwriting this behaviour here.
if (!EnableOfflineCaching)
Expand Down
23 changes: 18 additions & 5 deletions src/Sentry.Unity/SentryUnityOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ public sealed class SentryUnityOptions : SentryOptions
/// <summary>
/// The duration in [ms] for how long the game has to be unresponsive before an ANR event is reported.
/// </summary>
[Obsolete("The C# ANR watchdog is deprecated. Use Experimental.EnableNativeAppHangTracking instead. This property will be removed in a future version.")]
[Obsolete("The C# ANR watchdog is deprecated. Use EnableAppHangTracking instead. This property will be removed in a future version.")]
public TimeSpan AnrTimeout { get; set; } = TimeSpan.FromSeconds(5);

/// <summary>
Expand All @@ -187,18 +187,31 @@ public sealed class SentryUnityOptions : SentryOptions
public bool IosWatchdogTerminationIntegrationEnabled { get; set; } = false;

/// <summary>
/// Enables app hang detection on iOS through <c>sentry-cocoa</c>, which monitors the main thread.
/// App hang detection on Android, macOS, Windows, and Linux is experimental and controlled separately via
/// <c>Experimental.EnableNativeAppHangTracking</c>.
/// Enables experimental native app hang detection. This is disabled by default.
/// On iOS and macOS with the Cocoa backend, this uses <c>sentry-cocoa</c>. On Android and native desktop
/// backends, this uses <c>sentry-native</c>. Android requires <see cref="NdkIntegrationEnabled"/> and macOS
/// requires <see cref="ExperimentalSentryUnityOptions.MacosBackend"/> to be set to
/// <see cref="MacosBackend.Native"/> when using sentry-native.
/// </summary>
public bool EnableAppHangTracking { get; set; } = true;
public bool EnableAppHangTracking { get; set; } = false;

/// <summary>
/// The minimum duration for which the main thread must be blocked before <see cref="EnableAppHangTracking"/>
/// reports an app hang.
/// </summary>
public TimeSpan AppHangTimeout { get; set; } = TimeSpan.FromSeconds(5);

// TODO: Remove with the next mayor. This is so we still support the experimental option
internal bool NativeAppHangTrackingEnabled
{
get
{
#pragma warning disable CS0618 // Type or member is obsolete
return EnableAppHangTracking || Experimental.EnableNativeAppHangTracking;
#pragma warning restore CS0618 // Type or member is obsolete
}
}

/// <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
2 changes: 1 addition & 1 deletion src/Sentry.Unity/SentryUnityOptionsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public static void DisableUnhandledExceptionCapture(this SentryUnityOptions opti
/// <summary>
/// Disables the application-not-responding detection.
/// </summary>
[Obsolete("The C# ANR watchdog is deprecated. Use Experimental.EnableNativeAppHangTracking instead. This method will be removed in a future version.")]
[Obsolete("The C# ANR watchdog is deprecated. Use EnableAppHangTracking instead. This method will be removed in a future version.")]
public static void DisableAnrIntegration(this SentryUnityOptions options) =>
options.RemoveIntegration<AnrIntegration>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public override void Configure(SentryUnityOptions options)
#pragma warning restore CS0618 // Type or member is obsolete

// App Hang tracking
options.Experimental.EnableNativeAppHangTracking = true;
options.EnableAppHangTracking = true;
options.AppHangTimeout = TimeSpan.FromSeconds(2);

// Runtime initialization for integration tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,9 @@ public void ModifyManifest_AndroidAttachAnrThreadDump_FlowsThroughToManifest()
}

[Test]
public void ModifyManifest_NativeAppHangTracking_UsesExperimentalConfiguration()
public void ModifyManifest_NativeAppHangTracking_UsesAppHangConfiguration()
{
_fixture.SentryUnityOptions!.Experimental.EnableNativeAppHangTracking = true;
_fixture.SentryUnityOptions!.EnableAppHangTracking = true;
_fixture.SentryUnityOptions.AppHangTimeout = TimeSpan.FromSeconds(2);
var sut = _fixture.GetSut();

Expand Down
19 changes: 15 additions & 4 deletions test/Sentry.Unity.Tests/SentryUnityOptionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,17 +164,28 @@ public void Options_Experimental_LinuxBackend_IsSettable()
}

[Test]
public void Options_Experimental_EnableNativeAppHangTracking_DefaultsToFalse()
public void Options_EnableAppHangTracking_DefaultsToFalse()
{
var options = new SentryUnityOptions();
Assert.IsFalse(options.Experimental.EnableNativeAppHangTracking);
Assert.IsFalse(options.EnableAppHangTracking);
}

[Test]
public void Options_Experimental_EnableNativeAppHangTracking_IsSettable()
public void Options_EnableAppHangTracking_IsSettable()
{
var options = new SentryUnityOptions();
options.EnableAppHangTracking = true;
Assert.IsTrue(options.EnableAppHangTracking);
}

[Test]
public void Options_LegacyNativeAppHangTracking_EnablesNativeAppHangTracking()
{
var options = new SentryUnityOptions();
#pragma warning disable CS0618 // Type or member is obsolete
options.Experimental.EnableNativeAppHangTracking = true;
Assert.IsTrue(options.Experimental.EnableNativeAppHangTracking);
#pragma warning restore CS0618 // Type or member is obsolete

Assert.IsTrue(options.NativeAppHangTrackingEnabled);
}
}
Loading