From c236f00c64373da5136abac104af86782b68233e Mon Sep 17 00:00:00 2001 From: Bruno Garcia Date: Thu, 10 Jun 2021 01:12:00 -0400 Subject: [PATCH 01/20] release health --- .../Integrations/UnityApplicationLoggingIntegration.cs | 1 + src/Sentry.Unity/SentryUnity.cs | 2 +- src/sentry-dotnet | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Sentry.Unity/Integrations/UnityApplicationLoggingIntegration.cs b/src/Sentry.Unity/Integrations/UnityApplicationLoggingIntegration.cs index 13d61cb2d..f7e4f9dcf 100644 --- a/src/Sentry.Unity/Integrations/UnityApplicationLoggingIntegration.cs +++ b/src/Sentry.Unity/Integrations/UnityApplicationLoggingIntegration.cs @@ -75,6 +75,7 @@ private void OnQuitting() // 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. _application.LogMessageReceived -= OnLogMessageReceived; + _hub?.EndSession(); _hub?.FlushAsync(_sentryOptions?.ShutdownTimeout ?? TimeSpan.FromSeconds(1)).GetAwaiter().GetResult(); } diff --git a/src/Sentry.Unity/SentryUnity.cs b/src/Sentry.Unity/SentryUnity.cs index 1102db609..3c1a5c20b 100644 --- a/src/Sentry.Unity/SentryUnity.cs +++ b/src/Sentry.Unity/SentryUnity.cs @@ -1,6 +1,5 @@ using System; using System.ComponentModel; -using UnityEngine; namespace Sentry.Unity { @@ -32,6 +31,7 @@ public static void Init(SentryUnityOptions unitySentryOptions) SentryOptionsUtility.SetDefaults(unitySentryOptions); SentrySdk.Init(unitySentryOptions); + SentrySdk.StartSession(); } } } diff --git a/src/sentry-dotnet b/src/sentry-dotnet index 89fa5ad60..3d8f0a2d6 160000 --- a/src/sentry-dotnet +++ b/src/sentry-dotnet @@ -1 +1 @@ -Subproject commit 89fa5ad603c1d9696347ea22d220e204f2d926a2 +Subproject commit 3d8f0a2d68663344b508e9f456b85644b1f10d09 From ca9fdcac2a191233bbe6b97055d73903128c8646 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Thu, 10 Jun 2021 13:19:10 +0200 Subject: [PATCH 02/20] added release health integration & event listener --- src/Sentry.Unity/GameEventListener.cs | 29 +++++++++++++ .../Integrations/ReleaseHealthIntegration.cs | 43 +++++++++++++++++++ src/Sentry.Unity/SentryUnityOptions.cs | 1 + 3 files changed, 73 insertions(+) create mode 100644 src/Sentry.Unity/GameEventListener.cs create mode 100644 src/Sentry.Unity/Integrations/ReleaseHealthIntegration.cs diff --git a/src/Sentry.Unity/GameEventListener.cs b/src/Sentry.Unity/GameEventListener.cs new file mode 100644 index 000000000..5837afc44 --- /dev/null +++ b/src/Sentry.Unity/GameEventListener.cs @@ -0,0 +1,29 @@ +using System; +using UnityEngine; + +namespace Sentry.Unity +{ + public class GameEventListener : MonoBehaviour + { + public event Action? ApplicationPause; + public event Action? ApplicationFocus; + + private void Awake() + { + Debug.Log("Start listening to game events."); + } + + // Gets initially called by Awake + private void OnApplicationPause(bool pauseStatus) + { + Debug.Log($"Paused: {pauseStatus}"); + ApplicationPause?.Invoke(pauseStatus); + } + + private void OnApplicationFocus(bool hasFocus) + { + Debug.Log($"Has focus: {hasFocus}"); + ApplicationFocus?.Invoke(hasFocus); + } + } +} diff --git a/src/Sentry.Unity/Integrations/ReleaseHealthIntegration.cs b/src/Sentry.Unity/Integrations/ReleaseHealthIntegration.cs new file mode 100644 index 000000000..fa09a23b0 --- /dev/null +++ b/src/Sentry.Unity/Integrations/ReleaseHealthIntegration.cs @@ -0,0 +1,43 @@ +using Sentry.Integrations; +using UnityEngine; + +namespace Sentry.Unity.Integrations +{ + public class ReleaseHealthIntegration : ISdkIntegration + { + private readonly ISceneManager _sceneManager; + + public ReleaseHealthIntegration() : this(SceneManagerAdapter.Instance) + { + } + + internal ReleaseHealthIntegration(ISceneManager sceneManager) => _sceneManager = sceneManager; + + public void Register(IHub hub, SentryOptions options) + { + options.DiagnosticLogger?.Log(SentryLevel.Debug, "Registering SceneManager integration."); + + _sceneManager.ActiveSceneChanged += Sneak; + } + + private void Sneak(SceneAdapter fromScene, SceneAdapter toScene) + { + var gameListenerObject = new GameObject("SentryListener"); + gameListenerObject.hideFlags = HideFlags.HideInHierarchy; + + var gameListener = gameListenerObject.AddComponent(); + gameListener.ApplicationPause += OnApplicationPaused; + gameListener.ApplicationFocus += OnApplicationFocus; + } + + private void OnApplicationPaused(bool isPaused) + { + // Session magic here + } + + private void OnApplicationFocus(bool hasFocus) + { + // Session magic here + } + } +} diff --git a/src/Sentry.Unity/SentryUnityOptions.cs b/src/Sentry.Unity/SentryUnityOptions.cs index 72aba074c..ed7e624ac 100644 --- a/src/Sentry.Unity/SentryUnityOptions.cs +++ b/src/Sentry.Unity/SentryUnityOptions.cs @@ -92,6 +92,7 @@ public SentryUnityOptions() this.AddIntegration(new UnityApplicationLoggingIntegration()); this.AddIntegration(new UnityBeforeSceneLoadIntegration()); this.AddIntegration(new SceneManagerIntegration()); + this.AddIntegration(new ReleaseHealthIntegration()); } // Can't rely on Unity's OnEnable() hook. From e41e94b1ac6d2e312210d2c54a1a0ee17ec932b3 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Thu, 10 Jun 2021 13:22:41 +0200 Subject: [PATCH 03/20] renamed gameobject creation --- src/Sentry.Unity/Integrations/ReleaseHealthIntegration.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Sentry.Unity/Integrations/ReleaseHealthIntegration.cs b/src/Sentry.Unity/Integrations/ReleaseHealthIntegration.cs index fa09a23b0..6e2d67c94 100644 --- a/src/Sentry.Unity/Integrations/ReleaseHealthIntegration.cs +++ b/src/Sentry.Unity/Integrations/ReleaseHealthIntegration.cs @@ -17,10 +17,10 @@ public void Register(IHub hub, SentryOptions options) { options.DiagnosticLogger?.Log(SentryLevel.Debug, "Registering SceneManager integration."); - _sceneManager.ActiveSceneChanged += Sneak; + _sceneManager.ActiveSceneChanged += CreateEventListener; } - private void Sneak(SceneAdapter fromScene, SceneAdapter toScene) + private void CreateEventListener(SceneAdapter fromScene, SceneAdapter toScene) { var gameListenerObject = new GameObject("SentryListener"); gameListenerObject.hideFlags = HideFlags.HideInHierarchy; From 30b8378ae70ecc62a08b31d93b6f53fdab3958ea Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Thu, 10 Jun 2021 13:25:06 +0200 Subject: [PATCH 04/20] removed debugging log --- src/Sentry.Unity/GameEventListener.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Sentry.Unity/GameEventListener.cs b/src/Sentry.Unity/GameEventListener.cs index 5837afc44..654501182 100644 --- a/src/Sentry.Unity/GameEventListener.cs +++ b/src/Sentry.Unity/GameEventListener.cs @@ -8,12 +8,6 @@ public class GameEventListener : MonoBehaviour public event Action? ApplicationPause; public event Action? ApplicationFocus; - private void Awake() - { - Debug.Log("Start listening to game events."); - } - - // Gets initially called by Awake private void OnApplicationPause(bool pauseStatus) { Debug.Log($"Paused: {pauseStatus}"); From 69bc5da4af61a7429aba0f83d8ce6c091d5f3a1b Mon Sep 17 00:00:00 2001 From: Bruno Garcia Date: Thu, 10 Jun 2021 13:24:56 -0400 Subject: [PATCH 05/20] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 125faac97..ee0f363c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Features +- Release Health through Sessions ([#223](https://github.com/getsentry/sentry-unity/pull/223)) - Offline caching ([#208](https://github.com/getsentry/sentry-unity/pull/208)) - Breadcrumb categories added ([#206](https://github.com/getsentry/sentry-unity/pull/206)) - Bump Sentry .NET SDK 3.5.0 ([#218](https://github.com/getsentry/sentry-unity/pull/218)) From 7a77891e4645912b2a4d25b992034e69e2c90303 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Tue, 15 Jun 2021 17:09:00 +0200 Subject: [PATCH 06/20] poc session start/end log output --- src/Sentry.Unity/GameEventListener.cs | 35 ++++++++++++--- src/Sentry.Unity/Integrations/ITime.cs | 21 +++++++++ .../Integrations/ReleaseHealthIntegration.cs | 45 +++++++++++++++---- src/Sentry.Unity/SentryOptionsUtility.cs | 1 + src/Sentry.Unity/SentryUnityOptions.cs | 5 +++ test/Sentry.Unity.Tests/Stubs/TestHub.cs | 15 +++++++ 6 files changed, 108 insertions(+), 14 deletions(-) create mode 100644 src/Sentry.Unity/Integrations/ITime.cs diff --git a/src/Sentry.Unity/GameEventListener.cs b/src/Sentry.Unity/GameEventListener.cs index 654501182..4b04004bc 100644 --- a/src/Sentry.Unity/GameEventListener.cs +++ b/src/Sentry.Unity/GameEventListener.cs @@ -5,19 +5,42 @@ namespace Sentry.Unity { public class GameEventListener : MonoBehaviour { - public event Action? ApplicationPause; - public event Action? ApplicationFocus; + public event Action? ApplicationEnter; + public event Action? ApplicationExit; private void OnApplicationPause(bool pauseStatus) { - Debug.Log($"Paused: {pauseStatus}"); - ApplicationPause?.Invoke(pauseStatus); + if (Application.platform == RuntimePlatform.Android) + { + return; + } + + if (pauseStatus) + { + ApplicationExit?.Invoke(); + } + else + { + ApplicationEnter?.Invoke(); + } } private void OnApplicationFocus(bool hasFocus) { - Debug.Log($"Has focus: {hasFocus}"); - ApplicationFocus?.Invoke(hasFocus); + + if (Application.platform != RuntimePlatform.Android) + { + return; + } + + if (hasFocus) + { + ApplicationEnter?.Invoke(); + } + else + { + ApplicationExit?.Invoke(); + } } } } diff --git a/src/Sentry.Unity/Integrations/ITime.cs b/src/Sentry.Unity/Integrations/ITime.cs new file mode 100644 index 000000000..452f86005 --- /dev/null +++ b/src/Sentry.Unity/Integrations/ITime.cs @@ -0,0 +1,21 @@ +using System; +using UnityEngine; + +namespace Sentry.Unity +{ + internal interface ITime + { + DateTime Now { get; } + } + + internal sealed class TimeAdapter : ITime + { + public static readonly TimeAdapter Instance = new(); + + private TimeAdapter() + { + } + + public DateTime Now => System.DateTime.Now; + } +} diff --git a/src/Sentry.Unity/Integrations/ReleaseHealthIntegration.cs b/src/Sentry.Unity/Integrations/ReleaseHealthIntegration.cs index 6e2d67c94..9c5e04cc0 100644 --- a/src/Sentry.Unity/Integrations/ReleaseHealthIntegration.cs +++ b/src/Sentry.Unity/Integrations/ReleaseHealthIntegration.cs @@ -1,3 +1,4 @@ +using System; using Sentry.Integrations; using UnityEngine; @@ -6,12 +7,17 @@ namespace Sentry.Unity.Integrations public class ReleaseHealthIntegration : ISdkIntegration { private readonly ISceneManager _sceneManager; + private readonly ITime _time; - public ReleaseHealthIntegration() : this(SceneManagerAdapter.Instance) + public ReleaseHealthIntegration() : this(SceneManagerAdapter.Instance, TimeAdapter.Instance) { } - internal ReleaseHealthIntegration(ISceneManager sceneManager) => _sceneManager = sceneManager; + internal ReleaseHealthIntegration(ISceneManager sceneManager, ITime time) + { + _sceneManager = sceneManager; + _time = time; + } public void Register(IHub hub, SentryOptions options) { @@ -26,18 +32,41 @@ private void CreateEventListener(SceneAdapter fromScene, SceneAdapter toScene) gameListenerObject.hideFlags = HideFlags.HideInHierarchy; var gameListener = gameListenerObject.AddComponent(); - gameListener.ApplicationPause += OnApplicationPaused; - gameListener.ApplicationFocus += OnApplicationFocus; + gameListener.ApplicationEnter += OnApplicationEnter; + gameListener.ApplicationExit += OnApplicationExit; } - private void OnApplicationPaused(bool isPaused) + private void OnApplicationEnter() { - // Session magic here + // If a session has been running and not properly closed + if (PlayerPrefs.HasKey("ExitTime")) + { + var dateTimeString = PlayerPrefs.GetString("ExitTime"); + PlayerPrefs.DeleteKey("ExitTime"); + + var lastExit = Convert.ToDateTime(dateTimeString); + + var inactiveDuration = _time.Now - lastExit; + if (inactiveDuration.TotalSeconds >= 5.0f) + { + // TODO: fetch session end status + // SentrySdk.EndSession(); + Debug.Log("Session end"); + // SentrySdk.StartSession(); + Debug.Log("New Session start"); + } + } + else + { + // SentrySdk.StartSession(); + Debug.Log("Session start"); + } } - private void OnApplicationFocus(bool hasFocus) + private void OnApplicationExit() { - // Session magic here + // TODO: save the session end status as well + PlayerPrefs.SetString("ExitTime", _time.Now.ToString()); } } } diff --git a/src/Sentry.Unity/SentryOptionsUtility.cs b/src/Sentry.Unity/SentryOptionsUtility.cs index df472fe8e..62cbd0bb5 100644 --- a/src/Sentry.Unity/SentryOptionsUtility.cs +++ b/src/Sentry.Unity/SentryOptionsUtility.cs @@ -11,6 +11,7 @@ public static void SetDefaults(SentryUnityOptions options, IApplication? applica // 'Optimal' and 'Fastest' don't work on IL2CPP. Forcing 'NoCompression'. options.RequestBodyCompressionLevel = CompressionLevelWithAuto.NoCompression; + options.EnableAutoSessionTracking = false; SetRelease(options, application); SetEnvironment(options, application); diff --git a/src/Sentry.Unity/SentryUnityOptions.cs b/src/Sentry.Unity/SentryUnityOptions.cs index 7b0b3dc87..5fdd6c6b2 100644 --- a/src/Sentry.Unity/SentryUnityOptions.cs +++ b/src/Sentry.Unity/SentryUnityOptions.cs @@ -80,6 +80,11 @@ internal static string GetConfigPath(string? notDefaultConfigName = null) } } + /// + /// Whether the SDK should be tracking the session automatically. + /// + public bool EnableAutoSessionTracking { get; set; } = false; + public SentryUnityOptions() { // IL2CPP doesn't support Process.GetCurrentProcess().StartupTime diff --git a/test/Sentry.Unity.Tests/Stubs/TestHub.cs b/test/Sentry.Unity.Tests/Stubs/TestHub.cs index 77524b3ed..1a65a2094 100644 --- a/test/Sentry.Unity.Tests/Stubs/TestHub.cs +++ b/test/Sentry.Unity.Tests/Stubs/TestHub.cs @@ -33,6 +33,11 @@ public void CaptureTransaction(Transaction transaction) { } + public void CaptureSession(SessionUpdate sessionUpdate) + { + throw new NotImplementedException(); + } + public Task FlushAsync(TimeSpan timeout) { throw new NotImplementedException(); @@ -85,5 +90,15 @@ public void BindException(Exception exception, ISpan span) { throw new NotImplementedException(); } + + public void StartSession() + { + throw new NotImplementedException(); + } + + public void EndSession(SessionEndStatus status = SessionEndStatus.Exited) + { + throw new NotImplementedException(); + } } } From c9fafa37a97a19e070f8e899fd8665aec24b8011 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 16 Jun 2021 14:15:54 +0200 Subject: [PATCH 07/20] review changes --- src/Sentry.Unity/ApplicationFocusListener.cs | 75 +++++++++++++++++ src/Sentry.Unity/GameEventListener.cs | 46 ---------- src/Sentry.Unity/Integrations/ITime.cs | 21 ----- .../Integrations/ReleaseHealthIntegration.cs | 72 ---------------- .../Integrations/SessionIntegration.cs | 83 +++++++++++++++++++ src/Sentry.Unity/SentryOptionsUtility.cs | 2 +- src/Sentry.Unity/SentryUnityOptions.cs | 29 ++++++- 7 files changed, 186 insertions(+), 142 deletions(-) create mode 100644 src/Sentry.Unity/ApplicationFocusListener.cs delete mode 100644 src/Sentry.Unity/GameEventListener.cs delete mode 100644 src/Sentry.Unity/Integrations/ITime.cs delete mode 100644 src/Sentry.Unity/Integrations/ReleaseHealthIntegration.cs create mode 100644 src/Sentry.Unity/Integrations/SessionIntegration.cs diff --git a/src/Sentry.Unity/ApplicationFocusListener.cs b/src/Sentry.Unity/ApplicationFocusListener.cs new file mode 100644 index 000000000..7fae65177 --- /dev/null +++ b/src/Sentry.Unity/ApplicationFocusListener.cs @@ -0,0 +1,75 @@ +using System; +using UnityEngine; + +namespace Sentry.Unity +{ + /// + /// A MonoBehavior used to forward application focus events to subscribers. + /// + internal class ApplicationFocusListener : MonoBehaviour + { + /// + /// Hook to receive an event when the application gains focus. + /// + /// Listens to OnApplicationFocus for all platforms except Android, where we listen to OnApplicationPause. + /// + /// + public event Action? ApplicationFocusGaining; + + /// + /// Hook to receive an event when the application loses focus. + /// + /// Listens to OnApplicationFocus for all platforms except Android, where we listen to OnApplicationPause. + /// + /// + public event Action? ApplicationFocusLosing; + + /// + /// To receive Leaving/Resuming events on Android. + /// + /// https://docs.unity3d.com/2019.4/Documentation/ScriptReference/MonoBehaviour.OnApplicationPause.html + /// On Android, when the on-screen keyboard is enabled, it causes a OnApplicationFocus(false) event. + /// Additionally, if you press "Home" at the moment the keyboard is enabled, the OnApplicationFocus() event is + /// not called, but OnApplicationPause() is called instead. + /// + /// + private void OnApplicationPause(bool pauseStatus) + { + if (Application.platform != RuntimePlatform.Android) + { + return; + } + + if (pauseStatus) + { + ApplicationFocusLosing?.Invoke(); + } + else + { + ApplicationFocusGaining?.Invoke(); + } + } + + /// + /// To receive Leaving/Resuming events on all platforms except Android. + /// + /// + private void OnApplicationFocus(bool hasFocus) + { + // To avoid event duplication on Android + if (Application.platform == RuntimePlatform.Android) + { + return; + } + + if (hasFocus) + { + ApplicationFocusGaining?.Invoke(); + } + else + { + ApplicationFocusLosing?.Invoke(); + } + } + } +} diff --git a/src/Sentry.Unity/GameEventListener.cs b/src/Sentry.Unity/GameEventListener.cs deleted file mode 100644 index 4b04004bc..000000000 --- a/src/Sentry.Unity/GameEventListener.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using UnityEngine; - -namespace Sentry.Unity -{ - public class GameEventListener : MonoBehaviour - { - public event Action? ApplicationEnter; - public event Action? ApplicationExit; - - private void OnApplicationPause(bool pauseStatus) - { - if (Application.platform == RuntimePlatform.Android) - { - return; - } - - if (pauseStatus) - { - ApplicationExit?.Invoke(); - } - else - { - ApplicationEnter?.Invoke(); - } - } - - private void OnApplicationFocus(bool hasFocus) - { - - if (Application.platform != RuntimePlatform.Android) - { - return; - } - - if (hasFocus) - { - ApplicationEnter?.Invoke(); - } - else - { - ApplicationExit?.Invoke(); - } - } - } -} diff --git a/src/Sentry.Unity/Integrations/ITime.cs b/src/Sentry.Unity/Integrations/ITime.cs deleted file mode 100644 index 452f86005..000000000 --- a/src/Sentry.Unity/Integrations/ITime.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using UnityEngine; - -namespace Sentry.Unity -{ - internal interface ITime - { - DateTime Now { get; } - } - - internal sealed class TimeAdapter : ITime - { - public static readonly TimeAdapter Instance = new(); - - private TimeAdapter() - { - } - - public DateTime Now => System.DateTime.Now; - } -} diff --git a/src/Sentry.Unity/Integrations/ReleaseHealthIntegration.cs b/src/Sentry.Unity/Integrations/ReleaseHealthIntegration.cs deleted file mode 100644 index 9c5e04cc0..000000000 --- a/src/Sentry.Unity/Integrations/ReleaseHealthIntegration.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using Sentry.Integrations; -using UnityEngine; - -namespace Sentry.Unity.Integrations -{ - public class ReleaseHealthIntegration : ISdkIntegration - { - private readonly ISceneManager _sceneManager; - private readonly ITime _time; - - public ReleaseHealthIntegration() : this(SceneManagerAdapter.Instance, TimeAdapter.Instance) - { - } - - internal ReleaseHealthIntegration(ISceneManager sceneManager, ITime time) - { - _sceneManager = sceneManager; - _time = time; - } - - public void Register(IHub hub, SentryOptions options) - { - options.DiagnosticLogger?.Log(SentryLevel.Debug, "Registering SceneManager integration."); - - _sceneManager.ActiveSceneChanged += CreateEventListener; - } - - private void CreateEventListener(SceneAdapter fromScene, SceneAdapter toScene) - { - var gameListenerObject = new GameObject("SentryListener"); - gameListenerObject.hideFlags = HideFlags.HideInHierarchy; - - var gameListener = gameListenerObject.AddComponent(); - gameListener.ApplicationEnter += OnApplicationEnter; - gameListener.ApplicationExit += OnApplicationExit; - } - - private void OnApplicationEnter() - { - // If a session has been running and not properly closed - if (PlayerPrefs.HasKey("ExitTime")) - { - var dateTimeString = PlayerPrefs.GetString("ExitTime"); - PlayerPrefs.DeleteKey("ExitTime"); - - var lastExit = Convert.ToDateTime(dateTimeString); - - var inactiveDuration = _time.Now - lastExit; - if (inactiveDuration.TotalSeconds >= 5.0f) - { - // TODO: fetch session end status - // SentrySdk.EndSession(); - Debug.Log("Session end"); - // SentrySdk.StartSession(); - Debug.Log("New Session start"); - } - } - else - { - // SentrySdk.StartSession(); - Debug.Log("Session start"); - } - } - - private void OnApplicationExit() - { - // TODO: save the session end status as well - PlayerPrefs.SetString("ExitTime", _time.Now.ToString()); - } - } -} diff --git a/src/Sentry.Unity/Integrations/SessionIntegration.cs b/src/Sentry.Unity/Integrations/SessionIntegration.cs new file mode 100644 index 000000000..fdfa5bea7 --- /dev/null +++ b/src/Sentry.Unity/Integrations/SessionIntegration.cs @@ -0,0 +1,83 @@ +using System; +using Sentry.Extensibility; +using Sentry.Infrastructure; +using Sentry.Integrations; +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace Sentry.Unity.Integrations +{ + public class SessionIntegration : ISdkIntegration + { + private readonly ISceneManager _sceneManager; + private readonly ISystemClock _systemClock; + + private const string LastLeaveKey = "LastApplicationLeave"; + + public SessionIntegration() : this(SceneManagerAdapter.Instance, SystemClock.Clock) + { + } + + internal SessionIntegration(ISceneManager sceneManager, ISystemClock systemClock) + { + _sceneManager = sceneManager; + _systemClock = systemClock; + } + + public void Register(IHub hub, SentryOptions options) + { + if (options is not SentryUnityOptions {EnableAutoSessionTracking: true} unityOptions) + { + return; + } + + options.DiagnosticLogger?.LogDebug("Registering Session integration."); + + _sceneManager.ActiveSceneChanged += CreateFocusListenerGameObject; + void CreateFocusListenerGameObject(SceneAdapter fromScene, SceneAdapter toScene) + { + var gameListenerObject = new GameObject("SentryListener"); + gameListenerObject.hideFlags = HideFlags.HideInHierarchy; + + var gameListener = gameListenerObject.AddComponent(); + gameListener.ApplicationFocusGaining += () => + { + // No entry in PlayerPrefs means there has been no previous unclosed session. + if (!PlayerPrefs.HasKey(LastLeaveKey)) + { + // TODO: check for .NET init session to not override it + hub.StartSession(); + options.DiagnosticLogger?.LogDebug("Starting session."); + return; + } + + var dateTimeString = PlayerPrefs.GetString(LastLeaveKey); + PlayerPrefs.DeleteKey(LastLeaveKey); + + if (!DateTimeOffset.TryParse(dateTimeString, out var lastApplicationLeave)) + { + return; + } + + var inactiveDuration = _systemClock.GetUtcNow() - lastApplicationLeave; + if (inactiveDuration.TotalSeconds < unityOptions.SessionFocusTimeout) + { + return; + } + + // TODO: fetch session end status + options.DiagnosticLogger?.LogDebug("Ending session."); + hub.EndSession(); + options.DiagnosticLogger?.LogDebug("Starting new session."); + hub.StartSession(); + }; + + gameListener.ApplicationFocusLosing += () => + { + // TODO: write session end status + PlayerPrefs.SetString(LastLeaveKey, _systemClock.GetUtcNow().ToString()); + }; + } + } + } +} diff --git a/src/Sentry.Unity/SentryOptionsUtility.cs b/src/Sentry.Unity/SentryOptionsUtility.cs index 62cbd0bb5..8a488b8e7 100644 --- a/src/Sentry.Unity/SentryOptionsUtility.cs +++ b/src/Sentry.Unity/SentryOptionsUtility.cs @@ -11,7 +11,7 @@ public static void SetDefaults(SentryUnityOptions options, IApplication? applica // 'Optimal' and 'Fastest' don't work on IL2CPP. Forcing 'NoCompression'. options.RequestBodyCompressionLevel = CompressionLevelWithAuto.NoCompression; - options.EnableAutoSessionTracking = false; + options.EnableAutoSessionTracking = true; SetRelease(options, application); SetEnvironment(options, application); diff --git a/src/Sentry.Unity/SentryUnityOptions.cs b/src/Sentry.Unity/SentryUnityOptions.cs index 5fdd6c6b2..703de8e62 100644 --- a/src/Sentry.Unity/SentryUnityOptions.cs +++ b/src/Sentry.Unity/SentryUnityOptions.cs @@ -1,3 +1,4 @@ +using System; using System.IO; using System.Text.Json; using Sentry.Unity.Extensions; @@ -80,10 +81,34 @@ internal static string GetConfigPath(string? notDefaultConfigName = null) } } + /// + /// The timeout in [ms] between the application losing focus and regaining it to still count as one session. + /// + private float? _sessionFocusTimeout; + /// + /// The timeout in [ms] between the application losing focus and regaining it to still count as one session. + /// + /// + public float? SessionFocusTimeout + { + get => _sessionFocusTimeout; + set + { + if (value <= 0) + { + throw new InvalidOperationException($"The value {value} is not valid. Use a value greater than 0."); + } + _sessionFocusTimeout = value; + } + } + /// /// Whether the SDK should be tracking the session automatically. + /// + /// This will come from the .NET SDK main options and can be removed in the future. + /// /// - public bool EnableAutoSessionTracking { get; set; } = false; + public bool EnableAutoSessionTracking { get; set; } public SentryUnityOptions() { @@ -97,7 +122,7 @@ public SentryUnityOptions() this.AddIntegration(new UnityApplicationLoggingIntegration()); this.AddIntegration(new UnityBeforeSceneLoadIntegration()); this.AddIntegration(new SceneManagerIntegration()); - this.AddIntegration(new ReleaseHealthIntegration()); + this.AddIntegration(new SessionIntegration()); } // Can't rely on Unity's OnEnable() hook. From 2223d3631fc1125b100915921414fbdc9e728176 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 16 Jun 2021 18:18:42 +0200 Subject: [PATCH 08/20] default execution attribute --- src/Sentry.Unity/ApplicationFocusListener.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Sentry.Unity/ApplicationFocusListener.cs b/src/Sentry.Unity/ApplicationFocusListener.cs index 7fae65177..dbb6fcf1f 100644 --- a/src/Sentry.Unity/ApplicationFocusListener.cs +++ b/src/Sentry.Unity/ApplicationFocusListener.cs @@ -6,8 +6,14 @@ namespace Sentry.Unity /// /// A MonoBehavior used to forward application focus events to subscribers. /// + [DefaultExecutionOrder(-900)] internal class ApplicationFocusListener : MonoBehaviour { + private void Awake() + { + Debug.Log("VAR"); + } + /// /// Hook to receive an event when the application gains focus. /// From 5d45bec291e8a3a08f452fcd2d6b672358bfe7c4 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 16 Jun 2021 18:21:13 +0200 Subject: [PATCH 09/20] removed debug output --- src/Sentry.Unity/ApplicationFocusListener.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Sentry.Unity/ApplicationFocusListener.cs b/src/Sentry.Unity/ApplicationFocusListener.cs index dbb6fcf1f..228d11cb5 100644 --- a/src/Sentry.Unity/ApplicationFocusListener.cs +++ b/src/Sentry.Unity/ApplicationFocusListener.cs @@ -9,11 +9,6 @@ namespace Sentry.Unity [DefaultExecutionOrder(-900)] internal class ApplicationFocusListener : MonoBehaviour { - private void Awake() - { - Debug.Log("VAR"); - } - /// /// Hook to receive an event when the application gains focus. /// From c2617fca9ebb9445de17cd04dbc4fdf52da35748 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 16 Jun 2021 18:52:42 +0200 Subject: [PATCH 10/20] added default session timeout --- src/Sentry.Unity/SentryOptionsUtility.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Sentry.Unity/SentryOptionsUtility.cs b/src/Sentry.Unity/SentryOptionsUtility.cs index 8a488b8e7..98809b044 100644 --- a/src/Sentry.Unity/SentryOptionsUtility.cs +++ b/src/Sentry.Unity/SentryOptionsUtility.cs @@ -12,6 +12,7 @@ public static void SetDefaults(SentryUnityOptions options, IApplication? applica // 'Optimal' and 'Fastest' don't work on IL2CPP. Forcing 'NoCompression'. options.RequestBodyCompressionLevel = CompressionLevelWithAuto.NoCompression; options.EnableAutoSessionTracking = true; + options.SessionFocusTimeout = 5.0f; SetRelease(options, application); SetEnvironment(options, application); From 32537ea4cb1c10ff7e044355cad46596258aa0ca Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Mon, 21 Jun 2021 14:52:40 +0200 Subject: [PATCH 11/20] preparation for .net session tracking --- ...istener.cs => ApplicationPauseListener.cs} | 16 +++---- .../Integrations/SessionIntegration.cs | 48 ++++--------------- src/Sentry.Unity/SentryOptionsUtility.cs | 3 +- src/Sentry.Unity/SentryUnityOptions.cs | 29 ----------- 4 files changed, 17 insertions(+), 79 deletions(-) rename src/Sentry.Unity/{ApplicationFocusListener.cs => ApplicationPauseListener.cs} (82%) diff --git a/src/Sentry.Unity/ApplicationFocusListener.cs b/src/Sentry.Unity/ApplicationPauseListener.cs similarity index 82% rename from src/Sentry.Unity/ApplicationFocusListener.cs rename to src/Sentry.Unity/ApplicationPauseListener.cs index 228d11cb5..b572bf937 100644 --- a/src/Sentry.Unity/ApplicationFocusListener.cs +++ b/src/Sentry.Unity/ApplicationPauseListener.cs @@ -7,7 +7,7 @@ namespace Sentry.Unity /// A MonoBehavior used to forward application focus events to subscribers. /// [DefaultExecutionOrder(-900)] - internal class ApplicationFocusListener : MonoBehaviour + internal class ApplicationPauseListener : MonoBehaviour { /// /// Hook to receive an event when the application gains focus. @@ -15,7 +15,7 @@ internal class ApplicationFocusListener : MonoBehaviour /// Listens to OnApplicationFocus for all platforms except Android, where we listen to OnApplicationPause. /// /// - public event Action? ApplicationFocusGaining; + public event Action? ApplicationResuming; /// /// Hook to receive an event when the application loses focus. @@ -23,7 +23,7 @@ internal class ApplicationFocusListener : MonoBehaviour /// Listens to OnApplicationFocus for all platforms except Android, where we listen to OnApplicationPause. /// /// - public event Action? ApplicationFocusLosing; + public event Action? ApplicationPausing; /// /// To receive Leaving/Resuming events on Android. @@ -43,11 +43,11 @@ private void OnApplicationPause(bool pauseStatus) if (pauseStatus) { - ApplicationFocusLosing?.Invoke(); + ApplicationPausing?.Invoke(); } else { - ApplicationFocusGaining?.Invoke(); + ApplicationResuming?.Invoke(); } } @@ -57,7 +57,7 @@ private void OnApplicationPause(bool pauseStatus) /// private void OnApplicationFocus(bool hasFocus) { - // To avoid event duplication on Android + // To avoid event duplication on Android since the pause event will be handled via OnApplicationPause if (Application.platform == RuntimePlatform.Android) { return; @@ -65,11 +65,11 @@ private void OnApplicationFocus(bool hasFocus) if (hasFocus) { - ApplicationFocusGaining?.Invoke(); + ApplicationResuming?.Invoke(); } else { - ApplicationFocusLosing?.Invoke(); + ApplicationPausing?.Invoke(); } } } diff --git a/src/Sentry.Unity/Integrations/SessionIntegration.cs b/src/Sentry.Unity/Integrations/SessionIntegration.cs index fdfa5bea7..a873167d3 100644 --- a/src/Sentry.Unity/Integrations/SessionIntegration.cs +++ b/src/Sentry.Unity/Integrations/SessionIntegration.cs @@ -10,23 +10,19 @@ namespace Sentry.Unity.Integrations public class SessionIntegration : ISdkIntegration { private readonly ISceneManager _sceneManager; - private readonly ISystemClock _systemClock; - private const string LastLeaveKey = "LastApplicationLeave"; - - public SessionIntegration() : this(SceneManagerAdapter.Instance, SystemClock.Clock) + public SessionIntegration() : this(SceneManagerAdapter.Instance) { } - internal SessionIntegration(ISceneManager sceneManager, ISystemClock systemClock) + internal SessionIntegration(ISceneManager sceneManager) { _sceneManager = sceneManager; - _systemClock = systemClock; } public void Register(IHub hub, SentryOptions options) { - if (options is not SentryUnityOptions {EnableAutoSessionTracking: true} unityOptions) + if (!options.AutoSessionTracking) { return; } @@ -39,43 +35,15 @@ void CreateFocusListenerGameObject(SceneAdapter fromScene, SceneAdapter toScene) var gameListenerObject = new GameObject("SentryListener"); gameListenerObject.hideFlags = HideFlags.HideInHierarchy; - var gameListener = gameListenerObject.AddComponent(); - gameListener.ApplicationFocusGaining += () => + var gameListener = gameListenerObject.AddComponent(); + gameListener.ApplicationResuming += () => { - // No entry in PlayerPrefs means there has been no previous unclosed session. - if (!PlayerPrefs.HasKey(LastLeaveKey)) - { - // TODO: check for .NET init session to not override it - hub.StartSession(); - options.DiagnosticLogger?.LogDebug("Starting session."); - return; - } - - var dateTimeString = PlayerPrefs.GetString(LastLeaveKey); - PlayerPrefs.DeleteKey(LastLeaveKey); - - if (!DateTimeOffset.TryParse(dateTimeString, out var lastApplicationLeave)) - { - return; - } - - var inactiveDuration = _systemClock.GetUtcNow() - lastApplicationLeave; - if (inactiveDuration.TotalSeconds < unityOptions.SessionFocusTimeout) - { - return; - } - - // TODO: fetch session end status - options.DiagnosticLogger?.LogDebug("Ending session."); - hub.EndSession(); - options.DiagnosticLogger?.LogDebug("Starting new session."); - hub.StartSession(); + hub.ResumeSession(); }; - gameListener.ApplicationFocusLosing += () => + gameListener.ApplicationPausing += () => { - // TODO: write session end status - PlayerPrefs.SetString(LastLeaveKey, _systemClock.GetUtcNow().ToString()); + hub.PauseSession(); }; } } diff --git a/src/Sentry.Unity/SentryOptionsUtility.cs b/src/Sentry.Unity/SentryOptionsUtility.cs index 98809b044..df0fb3e2f 100644 --- a/src/Sentry.Unity/SentryOptionsUtility.cs +++ b/src/Sentry.Unity/SentryOptionsUtility.cs @@ -11,8 +11,7 @@ public static void SetDefaults(SentryUnityOptions options, IApplication? applica // 'Optimal' and 'Fastest' don't work on IL2CPP. Forcing 'NoCompression'. options.RequestBodyCompressionLevel = CompressionLevelWithAuto.NoCompression; - options.EnableAutoSessionTracking = true; - options.SessionFocusTimeout = 5.0f; + options.AutoSessionTracking = true; SetRelease(options, application); SetEnvironment(options, application); diff --git a/src/Sentry.Unity/SentryUnityOptions.cs b/src/Sentry.Unity/SentryUnityOptions.cs index 703de8e62..3b450d3f2 100644 --- a/src/Sentry.Unity/SentryUnityOptions.cs +++ b/src/Sentry.Unity/SentryUnityOptions.cs @@ -81,35 +81,6 @@ internal static string GetConfigPath(string? notDefaultConfigName = null) } } - /// - /// The timeout in [ms] between the application losing focus and regaining it to still count as one session. - /// - private float? _sessionFocusTimeout; - /// - /// The timeout in [ms] between the application losing focus and regaining it to still count as one session. - /// - /// - public float? SessionFocusTimeout - { - get => _sessionFocusTimeout; - set - { - if (value <= 0) - { - throw new InvalidOperationException($"The value {value} is not valid. Use a value greater than 0."); - } - _sessionFocusTimeout = value; - } - } - - /// - /// Whether the SDK should be tracking the session automatically. - /// - /// This will come from the .NET SDK main options and can be removed in the future. - /// - /// - public bool EnableAutoSessionTracking { get; set; } - public SentryUnityOptions() { // IL2CPP doesn't support Process.GetCurrentProcess().StartupTime From 18926f83942573383a9c6911ba887a95b6c4fc20 Mon Sep 17 00:00:00 2001 From: Bruno Garcia Date: Wed, 23 Jun 2021 14:49:53 -0400 Subject: [PATCH 12/20] wip --- src/sentry-dotnet | 2 +- test/Sentry.Unity.Tests/Stubs/TestHub.cs | 31 ++++++++++++++++++++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/sentry-dotnet b/src/sentry-dotnet index 3d8f0a2d6..e518cab2c 160000 --- a/src/sentry-dotnet +++ b/src/sentry-dotnet @@ -1 +1 @@ -Subproject commit 3d8f0a2d68663344b508e9f456b85644b1f10d09 +Subproject commit e518cab2cc857cffb5e052123e5283ee156124a6 diff --git a/test/Sentry.Unity.Tests/Stubs/TestHub.cs b/test/Sentry.Unity.Tests/Stubs/TestHub.cs index 77524b3ed..2e62e7fec 100644 --- a/test/Sentry.Unity.Tests/Stubs/TestHub.cs +++ b/test/Sentry.Unity.Tests/Stubs/TestHub.cs @@ -33,17 +33,18 @@ public void CaptureTransaction(Transaction transaction) { } + public void CaptureSession(SessionUpdate sessionUpdate) + { + } + public Task FlushAsync(TimeSpan timeout) { - throw new NotImplementedException(); + return Task.CompletedTask; } public void ConfigureScope(Action configureScope) => _configureScopeCalls.Add(configureScope); - public Task ConfigureScopeAsync(Func configureScope) - { - throw new NotImplementedException(); - } + public Task ConfigureScopeAsync(Func configureScope) => Task.CompletedTask; public void BindClient(ISentryClient client) { @@ -85,5 +86,25 @@ public void BindException(Exception exception, ISpan span) { throw new NotImplementedException(); } + + public void StartSession() + { + // TODO: test sessions + } + + public void PauseSession() + { + // TODO: test sessions + } + + public void ResumeSession() + { + // TODO: test sessions + } + + public void EndSession(SessionEndStatus status = SessionEndStatus.Exited) + { + // TODO: test sessions + } } } From f37af92b7a6b1e22635489095b248f9260514d59 Mon Sep 17 00:00:00 2001 From: Bruno Garcia Date: Wed, 23 Jun 2021 15:18:29 -0400 Subject: [PATCH 13/20] dotnet 3.6.0 --- src/sentry-dotnet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentry-dotnet b/src/sentry-dotnet index e518cab2c..4e835a344 160000 --- a/src/sentry-dotnet +++ b/src/sentry-dotnet @@ -1 +1 @@ -Subproject commit e518cab2cc857cffb5e052123e5283ee156124a6 +Subproject commit 4e835a3440ba93c1cb8532eed433545d69e55b7b From 1b1c082a81bf8a3762ad1d127b3063b2c3b7609e Mon Sep 17 00:00:00 2001 From: Bruno Garcia Date: Wed, 23 Jun 2021 19:46:43 -0400 Subject: [PATCH 14/20] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29dc7b06a..1abe4c5da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Sentry config is now a scriptable object ([#220](https://github.com/getsentry/sentry-unity/pull/220)) - Release Health through Sessions ([#223](https://github.com/getsentry/sentry-unity/pull/223)) - Unity protocol ([#234](https://github.com/getsentry/sentry-unity/pull/234)) +- Release health integration & Event-listener ([#225](https://github.com/getsentry/sentry-unity/pull/225)) ### Fixes From f831b31b4ccb3b7486fca83395569283db0c805c Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Thu, 24 Jun 2021 14:15:19 +0200 Subject: [PATCH 15/20] tweaked listener creation --- samples/Directory.Build.targets | 3 ++ src/Sentry.Unity/ApplicationPauseListener.cs | 18 ++++++++ .../Integrations/SessionIntegration.cs | 43 ++++++++----------- src/Sentry.Unity/SentryOptionsUtility.cs | 2 +- 4 files changed, 41 insertions(+), 25 deletions(-) create mode 100644 samples/Directory.Build.targets diff --git a/samples/Directory.Build.targets b/samples/Directory.Build.targets new file mode 100644 index 000000000..d6ad0385c --- /dev/null +++ b/samples/Directory.Build.targets @@ -0,0 +1,3 @@ + + + diff --git a/src/Sentry.Unity/ApplicationPauseListener.cs b/src/Sentry.Unity/ApplicationPauseListener.cs index b572bf937..1a9d7c402 100644 --- a/src/Sentry.Unity/ApplicationPauseListener.cs +++ b/src/Sentry.Unity/ApplicationPauseListener.cs @@ -25,6 +25,8 @@ internal class ApplicationPauseListener : MonoBehaviour /// public event Action? ApplicationPausing; + public event Action? ApplicationQuitting; + /// /// To receive Leaving/Resuming events on Android. /// @@ -72,5 +74,21 @@ private void OnApplicationFocus(bool hasFocus) ApplicationPausing?.Invoke(); } } + + private void OnApplicationQuit() + { + ApplicationQuitting?.Invoke(); + Destroy(gameObject); + } + + private void Awake() + { + Debug.Log("Listener created"); + } + + private void OnDestroy() + { + Debug.Log("Listener destroyed"); + } } } diff --git a/src/Sentry.Unity/Integrations/SessionIntegration.cs b/src/Sentry.Unity/Integrations/SessionIntegration.cs index a873167d3..ad8ba4bef 100644 --- a/src/Sentry.Unity/Integrations/SessionIntegration.cs +++ b/src/Sentry.Unity/Integrations/SessionIntegration.cs @@ -9,16 +9,8 @@ namespace Sentry.Unity.Integrations { public class SessionIntegration : ISdkIntegration { - private readonly ISceneManager _sceneManager; - - public SessionIntegration() : this(SceneManagerAdapter.Instance) - { - } - - internal SessionIntegration(ISceneManager sceneManager) - { - _sceneManager = sceneManager; - } + public SessionIntegration() + { } public void Register(IHub hub, SentryOptions options) { @@ -29,23 +21,26 @@ public void Register(IHub hub, SentryOptions options) options.DiagnosticLogger?.LogDebug("Registering Session integration."); - _sceneManager.ActiveSceneChanged += CreateFocusListenerGameObject; - void CreateFocusListenerGameObject(SceneAdapter fromScene, SceneAdapter toScene) + var gameListenerObject = new GameObject("SentryListener"); + gameListenerObject.hideFlags = HideFlags.HideAndDontSave; + + var gameListener = gameListenerObject.AddComponent(); + gameListener.ApplicationResuming += () => { - var gameListenerObject = new GameObject("SentryListener"); - gameListenerObject.hideFlags = HideFlags.HideInHierarchy; + Debug.Log("resuming"); + hub.ResumeSession(); + }; - var gameListener = gameListenerObject.AddComponent(); - gameListener.ApplicationResuming += () => - { - hub.ResumeSession(); - }; + gameListener.ApplicationPausing += () => + { + Debug.Log("pausing"); + hub.PauseSession(); + }; - gameListener.ApplicationPausing += () => - { - hub.PauseSession(); - }; - } + gameListener.ApplicationQuitting += () => + { + Debug.Log("quitting"); + }; } } } diff --git a/src/Sentry.Unity/SentryOptionsUtility.cs b/src/Sentry.Unity/SentryOptionsUtility.cs index d9bb71ace..a9618b90b 100644 --- a/src/Sentry.Unity/SentryOptionsUtility.cs +++ b/src/Sentry.Unity/SentryOptionsUtility.cs @@ -10,7 +10,7 @@ public static void SetDefaults(SentryUnityOptions options, IApplication? applica options.Enabled = true; options.Dsn = null; - options.AutoSessionTracking = false; + options.AutoSessionTracking = true; options.CaptureInEditor = true; options.RequestBodyCompressionLevel = CompressionLevelWithAuto.NoCompression; options.AttachStacktrace = false; From c64184cc3c70fda3108f69d72e66a7d67fd88a34 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Thu, 24 Jun 2021 18:32:34 +0200 Subject: [PATCH 16/20] changed 'DebugOnlyInEditor' default to false --- src/Sentry.Unity/SentryOptionsUtility.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Sentry.Unity/SentryOptionsUtility.cs b/src/Sentry.Unity/SentryOptionsUtility.cs index a9618b90b..219b983d9 100644 --- a/src/Sentry.Unity/SentryOptionsUtility.cs +++ b/src/Sentry.Unity/SentryOptionsUtility.cs @@ -1,3 +1,4 @@ +using System; using Sentry.Unity.Integrations; namespace Sentry.Unity @@ -11,6 +12,7 @@ public static void SetDefaults(SentryUnityOptions options, IApplication? applica options.Enabled = true; options.Dsn = null; options.AutoSessionTracking = true; + options.AutoSessionTrackingInterval = TimeSpan.FromSeconds(5); options.CaptureInEditor = true; options.RequestBodyCompressionLevel = CompressionLevelWithAuto.NoCompression; options.AttachStacktrace = false; @@ -25,7 +27,7 @@ public static void SetDefaults(SentryUnityOptions options, IApplication? applica options.CacheDirectoryPath = application.PersistentDataPath; options.Debug = true; - options.DebugOnlyInEditor = true; + options.DebugOnlyInEditor = false; options.DiagnosticLevel = SentryLevel.Warning; TryAttachLogger(options, application); @@ -45,7 +47,7 @@ public static void SetDefaults(ScriptableSentryUnityOptions options) options.EnableOfflineCaching = true; options.Debug = true; - options.DebugOnlyInEditor = true; + options.DebugOnlyInEditor = false; options.DiagnosticLevel = SentryLevel.Warning; } From a2a8c0a571077154ceb1725c3a54761c3f848bdf Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Fri, 25 Jun 2021 12:30:33 +0200 Subject: [PATCH 17/20] session restarting cleanup --- src/Sentry.Unity/ApplicationPauseListener.cs | 32 +++++++++++-------- .../Integrations/SessionIntegration.cs | 21 +++--------- src/Sentry.Unity/SentryUnity.cs | 1 - 3 files changed, 22 insertions(+), 32 deletions(-) diff --git a/src/Sentry.Unity/ApplicationPauseListener.cs b/src/Sentry.Unity/ApplicationPauseListener.cs index 1a9d7c402..9cf70c4cf 100644 --- a/src/Sentry.Unity/ApplicationPauseListener.cs +++ b/src/Sentry.Unity/ApplicationPauseListener.cs @@ -25,7 +25,9 @@ internal class ApplicationPauseListener : MonoBehaviour /// public event Action? ApplicationPausing; - public event Action? ApplicationQuitting; + // OnApplicationPause and OnApplicationFocus get called during startup and would fire false resume events + private bool _pauseInit; + private bool _focusInit; /// /// To receive Leaving/Resuming events on Android. @@ -38,6 +40,12 @@ internal class ApplicationPauseListener : MonoBehaviour /// private void OnApplicationPause(bool pauseStatus) { + if (!_pauseInit) + { + _pauseInit = true; + return; + } + if (Application.platform != RuntimePlatform.Android) { return; @@ -47,7 +55,7 @@ private void OnApplicationPause(bool pauseStatus) { ApplicationPausing?.Invoke(); } - else + else if (!pauseStatus) { ApplicationResuming?.Invoke(); } @@ -59,6 +67,12 @@ private void OnApplicationPause(bool pauseStatus) /// private void OnApplicationFocus(bool hasFocus) { + if (!_focusInit) + { + _focusInit = true; + return; + } + // To avoid event duplication on Android since the pause event will be handled via OnApplicationPause if (Application.platform == RuntimePlatform.Android) { @@ -69,26 +83,16 @@ private void OnApplicationFocus(bool hasFocus) { ApplicationResuming?.Invoke(); } - else + else if (!hasFocus) { ApplicationPausing?.Invoke(); } } + // The GameObject has to destroy itself since it was created with HideFlags.HideAndDontSave private void OnApplicationQuit() { - ApplicationQuitting?.Invoke(); Destroy(gameObject); } - - private void Awake() - { - Debug.Log("Listener created"); - } - - private void OnDestroy() - { - Debug.Log("Listener destroyed"); - } } } diff --git a/src/Sentry.Unity/Integrations/SessionIntegration.cs b/src/Sentry.Unity/Integrations/SessionIntegration.cs index ad8ba4bef..010349a17 100644 --- a/src/Sentry.Unity/Integrations/SessionIntegration.cs +++ b/src/Sentry.Unity/Integrations/SessionIntegration.cs @@ -1,17 +1,11 @@ -using System; using Sentry.Extensibility; -using Sentry.Infrastructure; using Sentry.Integrations; using UnityEngine; -using UnityEngine.SceneManagement; namespace Sentry.Unity.Integrations { public class SessionIntegration : ISdkIntegration { - public SessionIntegration() - { } - public void Register(IHub hub, SentryOptions options) { if (!options.AutoSessionTracking) @@ -21,26 +15,19 @@ public void Register(IHub hub, SentryOptions options) options.DiagnosticLogger?.LogDebug("Registering Session integration."); - var gameListenerObject = new GameObject("SentryListener"); - gameListenerObject.hideFlags = HideFlags.HideAndDontSave; - + // HideFlags.HideAndDontSave hides the GameObject in the hierarchy and prevents changing of scenes from destroying it + var gameListenerObject = new GameObject("SentryListener") {hideFlags = HideFlags.HideAndDontSave}; var gameListener = gameListenerObject.AddComponent(); gameListener.ApplicationResuming += () => { - Debug.Log("resuming"); + options.DiagnosticLogger?.LogDebug("Resuming session."); hub.ResumeSession(); }; - gameListener.ApplicationPausing += () => { - Debug.Log("pausing"); + options.DiagnosticLogger?.LogDebug("Pausing session."); hub.PauseSession(); }; - - gameListener.ApplicationQuitting += () => - { - Debug.Log("quitting"); - }; } } } diff --git a/src/Sentry.Unity/SentryUnity.cs b/src/Sentry.Unity/SentryUnity.cs index 0b8421c30..e385b733d 100644 --- a/src/Sentry.Unity/SentryUnity.cs +++ b/src/Sentry.Unity/SentryUnity.cs @@ -33,7 +33,6 @@ internal static void Init(SentryUnityOptions unitySentryOptions) unitySentryOptions.DiagnosticLogger?.LogDebug(unitySentryOptions.ToString()); SentrySdk.Init(unitySentryOptions); - SentrySdk.StartSession(); } } } From 8f0f41b7aab6834158a7be1c209a289f6ac289ad Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Fri, 25 Jun 2021 15:22:57 +0200 Subject: [PATCH 18/20] cleanup --- src/Sentry.Unity/ApplicationPauseListener.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Sentry.Unity/ApplicationPauseListener.cs b/src/Sentry.Unity/ApplicationPauseListener.cs index 9cf70c4cf..fc5b6baaa 100644 --- a/src/Sentry.Unity/ApplicationPauseListener.cs +++ b/src/Sentry.Unity/ApplicationPauseListener.cs @@ -55,7 +55,7 @@ private void OnApplicationPause(bool pauseStatus) { ApplicationPausing?.Invoke(); } - else if (!pauseStatus) + else { ApplicationResuming?.Invoke(); } @@ -83,7 +83,7 @@ private void OnApplicationFocus(bool hasFocus) { ApplicationResuming?.Invoke(); } - else if (!hasFocus) + else { ApplicationPausing?.Invoke(); } From 81bc92584d02ea71349cdd71821ebd2f4363cfad Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Fri, 25 Jun 2021 15:49:56 +0200 Subject: [PATCH 19/20] internal running state --- src/Sentry.Unity/ApplicationPauseListener.cs | 29 +++++++------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/Sentry.Unity/ApplicationPauseListener.cs b/src/Sentry.Unity/ApplicationPauseListener.cs index fc5b6baaa..d29f67beb 100644 --- a/src/Sentry.Unity/ApplicationPauseListener.cs +++ b/src/Sentry.Unity/ApplicationPauseListener.cs @@ -25,9 +25,8 @@ internal class ApplicationPauseListener : MonoBehaviour /// public event Action? ApplicationPausing; - // OnApplicationPause and OnApplicationFocus get called during startup and would fire false resume events - private bool _pauseInit; - private bool _focusInit; + // Keeping internal track of running state because OnApplicationPause and OnApplicationFocus get called during startup and would fire false resume events + private bool _isRunning = true; /// /// To receive Leaving/Resuming events on Android. @@ -40,23 +39,19 @@ internal class ApplicationPauseListener : MonoBehaviour /// private void OnApplicationPause(bool pauseStatus) { - if (!_pauseInit) - { - _pauseInit = true; - return; - } - if (Application.platform != RuntimePlatform.Android) { return; } - if (pauseStatus) + if (pauseStatus && _isRunning) { + _isRunning = false; ApplicationPausing?.Invoke(); } - else + else if (!pauseStatus && !_isRunning) { + _isRunning = true; ApplicationResuming?.Invoke(); } } @@ -67,24 +62,20 @@ private void OnApplicationPause(bool pauseStatus) /// private void OnApplicationFocus(bool hasFocus) { - if (!_focusInit) - { - _focusInit = true; - return; - } - // To avoid event duplication on Android since the pause event will be handled via OnApplicationPause if (Application.platform == RuntimePlatform.Android) { return; } - if (hasFocus) + if (hasFocus && !_isRunning) { + _isRunning = true; ApplicationResuming?.Invoke(); } - else + else if (!hasFocus && _isRunning) { + _isRunning = false; ApplicationPausing?.Invoke(); } } From 651d725f93ef6cdcdbb48aad9f21914c1e62e6af Mon Sep 17 00:00:00 2001 From: Bruno Garcia Date: Fri, 25 Jun 2021 10:19:31 -0400 Subject: [PATCH 20/20] Apply suggestions from code review --- CHANGELOG.md | 1 - src/Sentry.Unity/ApplicationPauseListener.cs | 7 ++----- src/Sentry.Unity/SentryOptionsUtility.cs | 1 - 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1abe4c5da..41ac6856e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,6 @@ ### Features - Sentry config is now a scriptable object ([#220](https://github.com/getsentry/sentry-unity/pull/220)) -- Release Health through Sessions ([#223](https://github.com/getsentry/sentry-unity/pull/223)) - Unity protocol ([#234](https://github.com/getsentry/sentry-unity/pull/234)) - Release health integration & Event-listener ([#225](https://github.com/getsentry/sentry-unity/pull/225)) diff --git a/src/Sentry.Unity/ApplicationPauseListener.cs b/src/Sentry.Unity/ApplicationPauseListener.cs index d29f67beb..668463018 100644 --- a/src/Sentry.Unity/ApplicationPauseListener.cs +++ b/src/Sentry.Unity/ApplicationPauseListener.cs @@ -31,11 +31,11 @@ internal class ApplicationPauseListener : MonoBehaviour /// /// To receive Leaving/Resuming events on Android. /// - /// https://docs.unity3d.com/2019.4/Documentation/ScriptReference/MonoBehaviour.OnApplicationPause.html /// On Android, when the on-screen keyboard is enabled, it causes a OnApplicationFocus(false) event. /// Additionally, if you press "Home" at the moment the keyboard is enabled, the OnApplicationFocus() event is /// not called, but OnApplicationPause() is called instead. /// + /// /// private void OnApplicationPause(bool pauseStatus) { @@ -81,9 +81,6 @@ private void OnApplicationFocus(bool hasFocus) } // The GameObject has to destroy itself since it was created with HideFlags.HideAndDontSave - private void OnApplicationQuit() - { - Destroy(gameObject); - } + private void OnApplicationQuit() => Destroy(gameObject); } } diff --git a/src/Sentry.Unity/SentryOptionsUtility.cs b/src/Sentry.Unity/SentryOptionsUtility.cs index 219b983d9..314ca1296 100644 --- a/src/Sentry.Unity/SentryOptionsUtility.cs +++ b/src/Sentry.Unity/SentryOptionsUtility.cs @@ -12,7 +12,6 @@ public static void SetDefaults(SentryUnityOptions options, IApplication? applica options.Enabled = true; options.Dsn = null; options.AutoSessionTracking = true; - options.AutoSessionTrackingInterval = TimeSpan.FromSeconds(5); options.CaptureInEditor = true; options.RequestBodyCompressionLevel = CompressionLevelWithAuto.NoCompression; options.AttachStacktrace = false;