diff --git a/src/Sentry.Unity/Integrations/LifeCycleIntegration.cs b/src/Sentry.Unity/Integrations/LifeCycleIntegration.cs new file mode 100644 index 000000000..55f5b0019 --- /dev/null +++ b/src/Sentry.Unity/Integrations/LifeCycleIntegration.cs @@ -0,0 +1,76 @@ +using Sentry.Extensibility; +using Sentry.Integrations; + +namespace Sentry.Unity.Integrations; + +internal class LifeCycleIntegration : ISdkIntegration +{ + private readonly SentryMonoBehaviour _sentryMonoBehaviour; + private readonly IApplication _application; + + public LifeCycleIntegration(SentryMonoBehaviour sentryMonoBehaviour, IApplication? application = null) + { + _sentryMonoBehaviour = sentryMonoBehaviour; + _application = application ?? ApplicationAdapter.Instance; + } + + public void Register(IHub hub, SentryOptions options) + { + _sentryMonoBehaviour.ApplicationResuming += () => OnApplicationResuming(hub, options); + _sentryMonoBehaviour.ApplicationPausing += () => OnApplicationPausing(hub, options); + _application.Quitting += () => OnApplicationQuitting(hub, options); + } + + private static void OnApplicationResuming(IHub hub, SentryOptions options) + { + if (!options.AutoSessionTracking) + { + return; + } + + if (hub.IsSessionActive) + { + options.DiagnosticLogger?.LogDebug("Resuming session."); + hub.ResumeSession(); + } + else + { + options.DiagnosticLogger?.LogDebug("No active session to resume found. Starting a new session."); + hub.StartSession(); + } + } + + private static void OnApplicationPausing(IHub hub, SentryOptions options) + { + if (!options.AutoSessionTracking) + { + return; + } + + if (hub.IsSessionActive) + { + options.DiagnosticLogger?.LogDebug("Pausing session."); + hub.PauseSession(); + } + } + + private static void OnApplicationQuitting(IHub hub, SentryOptions options) + { + options.DiagnosticLogger?.LogInfo("Quitting. Pausing session and flushing."); + + // Note: iOS applications are usually suspended and do not quit. You should tick "Exit on Suspend" in Player settings for iOS builds to cause the game to quit and not suspend, otherwise you may not see this call. + // If "Exit on Suspend" is not ticked then you will see calls to OnApplicationPause instead. + // Note: On Windows Store Apps and Windows Phone 8.1 there is no application quit event. Consider using OnApplicationFocus event when focusStatus equals false. + // Note: On WebGL it is not possible to implement OnApplicationQuit due to nature of the browser tabs closing. + + // 'OnQuitting' is invoked even when an uncaught exception happens in the ART. To make sure the .NET + // SDK checks with the native layer on restart if the previous run crashed (through the CrashedLastRun callback) + // we'll just pause sessions on shutdown. On restart, they can be closed with the right timestamp and as 'exited'. + if (options.AutoSessionTracking && hub.IsSessionActive) + { + hub.PauseSession(); + } + + hub.FlushAsync(options.ShutdownTimeout).GetAwaiter().GetResult(); + } +} diff --git a/src/Sentry.Unity/Integrations/SessionIntegration.cs b/src/Sentry.Unity/Integrations/SessionIntegration.cs deleted file mode 100644 index c966d2227..000000000 --- a/src/Sentry.Unity/Integrations/SessionIntegration.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Sentry.Extensibility; -using Sentry.Integrations; - -namespace Sentry.Unity.Integrations; - -internal class SessionIntegration : ISdkIntegration -{ - private readonly SentryMonoBehaviour _sentryMonoBehaviour; - - public SessionIntegration(SentryMonoBehaviour sentryMonoBehaviour) - { - _sentryMonoBehaviour = sentryMonoBehaviour; - } - - public void Register(IHub hub, SentryOptions options) - { - if (!options.AutoSessionTracking) - { - return; - } - - _sentryMonoBehaviour.ApplicationResuming += () => - { - options.DiagnosticLogger?.LogDebug("Resuming session."); - hub.ResumeSession(); - }; - _sentryMonoBehaviour.ApplicationPausing += () => - { - options.DiagnosticLogger?.LogDebug("Pausing session."); - hub.PauseSession(); - }; - } -} diff --git a/src/Sentry.Unity/Integrations/UnityErrorLogException.cs b/src/Sentry.Unity/Integrations/UnityErrorLogException.cs index 8d7a6daeb..5379236ee 100644 --- a/src/Sentry.Unity/Integrations/UnityErrorLogException.cs +++ b/src/Sentry.Unity/Integrations/UnityErrorLogException.cs @@ -54,7 +54,9 @@ public SentryException ToSentryException() Mechanism = new Mechanism { Handled = true, - Type = "unity.log" + Type = "Debug.LogError", + Synthetic = true, + Data = { {Mechanism.TerminalKey, false} } } }; } diff --git a/src/Sentry.Unity/Integrations/UnityLogHandlerIntegration.cs b/src/Sentry.Unity/Integrations/UnityLogHandlerIntegration.cs index b93b15a1a..d7d03f3be 100644 --- a/src/Sentry.Unity/Integrations/UnityLogHandlerIntegration.cs +++ b/src/Sentry.Unity/Integrations/UnityLogHandlerIntegration.cs @@ -43,8 +43,6 @@ public void Register(IHub hub, SentryOptions sentryOptions) _unityLogHandler = Debug.unityLogger.logHandler; Debug.unityLogger.logHandler = this; - - _application.Quitting += OnQuitting; } public void LogException(Exception exception, UnityEngine.Object context) @@ -72,8 +70,7 @@ internal void CaptureException(Exception exception, UnityEngine.Object? context) // NOTE: This might not be entirely true, as a user could as well call `Debug.LogException` // and expect a handled exception but it is not possible for us to differentiate // https://docs.sentry.io/platforms/unity/troubleshooting/#unhandled-exceptions---debuglogexception - exception.Data[Mechanism.HandledKey] = false; - exception.Data[Mechanism.MechanismKey] = "Unity.LogException"; + exception.SetSentryMechanism("Unity.LogException", handled: false, terminal: false); _ = _hub.CaptureException(exception); } @@ -84,23 +81,4 @@ public void LogFormat(LogType logType, UnityEngine.Object? context, string forma // The LogHandler does not have access to the stacktrace information required _unityLogHandler.LogFormat(logType, context, format, args); } - - private void OnQuitting() - { - _sentryOptions?.DiagnosticLogger?.LogInfo("OnQuitting was invoked. Unhooking log callback and pausing session."); - - // Note: iOS applications are usually suspended and do not quit. You should tick "Exit on Suspend" in Player settings for iOS builds to cause the game to quit and not suspend, otherwise you may not see this call. - // If "Exit on Suspend" is not ticked then you will see calls to OnApplicationPause instead. - // Note: On Windows Store Apps and Windows Phone 8.1 there is no application quit event. Consider using OnApplicationFocus event when focusStatus equals false. - // Note: On WebGL it is not possible to implement OnApplicationQuit due to nature of the browser tabs closing. - - // 'OnQuitting' is invoked even when an uncaught exception happens in the ART. To make sure the .NET - // SDK checks with the native layer on restart if the previous run crashed (through the CrashedLastRun callback) - // we'll just pause sessions on shutdown. On restart they can be closed with the right timestamp and as 'exited'. - if (_sentryOptions?.AutoSessionTracking is true) - { - _hub?.PauseSession(); - } - _hub?.FlushAsync(_sentryOptions?.ShutdownTimeout ?? TimeSpan.FromSeconds(1)).GetAwaiter().GetResult(); - } } diff --git a/src/Sentry.Unity/SentryUnityOptions.cs b/src/Sentry.Unity/SentryUnityOptions.cs index e0008f79c..63bb44862 100644 --- a/src/Sentry.Unity/SentryUnityOptions.cs +++ b/src/Sentry.Unity/SentryUnityOptions.cs @@ -348,7 +348,7 @@ internal SentryUnityOptions(IApplication? application = null, AddIntegration(new UnityBeforeSceneLoadIntegration()); AddIntegration(new SceneManagerIntegration()); AddIntegration(new SceneManagerTracingIntegration()); - AddIntegration(new SessionIntegration(behaviour)); + AddIntegration(new LifeCycleIntegration(behaviour)); AddIntegration(new TraceGenerationIntegration(behaviour)); AddExceptionFilter(new UnityBadGatewayExceptionFilter()); diff --git a/src/sentry-dotnet b/src/sentry-dotnet index 080493bf5..2805139a3 160000 --- a/src/sentry-dotnet +++ b/src/sentry-dotnet @@ -1 +1 @@ -Subproject commit 080493bf59dc5fbf49bcae0a4d203bce0c86447a +Subproject commit 2805139a3f1dd994f0731e83b9742514868eac6c diff --git a/test/Sentry.Unity.Tests/SessionIntegrationTests.cs b/test/Sentry.Unity.Tests/LifeCycleIntegrationTests.cs similarity index 96% rename from test/Sentry.Unity.Tests/SessionIntegrationTests.cs rename to test/Sentry.Unity.Tests/LifeCycleIntegrationTests.cs index d53f81698..598715499 100644 --- a/test/Sentry.Unity.Tests/SessionIntegrationTests.cs +++ b/test/Sentry.Unity.Tests/LifeCycleIntegrationTests.cs @@ -6,7 +6,7 @@ namespace Sentry.Unity.Tests; -public class SessionIntegrationTests +public class LifeCycleIntegrationTests { [UnityTest] public IEnumerator SessionIntegration_Init_SentryMonoBehaviourCreated()