From 7a5e02b9f11af3c36e3de17104117bdfcc805065 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos Date: Thu, 3 Feb 2022 20:13:25 +0100 Subject: [PATCH 1/5] wip: setting native context --- .../NativeScopeObserver.cs | 2 +- src/Sentry.Unity.Native/SentryNativeBridge.cs | 70 +++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/Sentry.Unity.Native/NativeScopeObserver.cs b/src/Sentry.Unity.Native/NativeScopeObserver.cs index e08aa2d60..c6ff4bd5d 100644 --- a/src/Sentry.Unity.Native/NativeScopeObserver.cs +++ b/src/Sentry.Unity.Native/NativeScopeObserver.cs @@ -19,7 +19,7 @@ public void AddBreadcrumb(Breadcrumb breadcrumb) _options.DiagnosticLogger?.LogDebug("Native Scope Sync - Adding breadcrumb m:\"{0}\" l:\"{1}\"", breadcrumb.Message, breadcrumb.Level); - // TODO implement + SentryNativeBridge.AddBreadcrumb(breadcrumb); } public void SetExtra(string key, object? value) diff --git a/src/Sentry.Unity.Native/SentryNativeBridge.cs b/src/Sentry.Unity.Native/SentryNativeBridge.cs index 47ba6502c..dbed963c4 100644 --- a/src/Sentry.Unity.Native/SentryNativeBridge.cs +++ b/src/Sentry.Unity.Native/SentryNativeBridge.cs @@ -32,6 +32,37 @@ public static void Init(SentryUnityOptions options) sentry_init(cOptions); } + public static void AddBreadcrumb(Breadcrumb breadcrumb) + { + // see https://develop.sentry.dev/sdk/event-payloads/breadcrumbs/ + var crumb = sentry_value_new_breadcrumb(breadcrumb.Type, breadcrumb.Message); + sentry_value_set_by_key(crumb, "level", sentry_value_new_string(breadcrumb.Level.ToString().ToLower())); + sentry_value_set_by_key(crumb, "timestamp", sentry_value_new_string(GetTimestamp(breadcrumb.Timestamp))); + if (breadcrumb.Category is not null) + { + sentry_value_set_by_key(crumb, "category", sentry_value_new_string(breadcrumb.Category)); + } + sentry_add_breadcrumb(crumb); + } + + public static void SetExtra(string key, string? value) + { + // TODO + } + + public static void SetTag(string key, string value) => sentry_set_tag(key, value); + + public static void UnsetTag(string key) => sentry_remove_tag(key); + + public static void SetUser(string? email, string? userId, string? ipAddress, string? username) + { + var user = sentry_value_new_object(); + // TODO + sentry_set_user(user); + } + + public static void UnsetUser() => sentry_remove_user(); + // libsentry.so [DllImport("sentry")] private static extern IntPtr sentry_options_new(); @@ -49,6 +80,30 @@ public static void Init(SentryUnityOptions options) [DllImport("sentry")] private static extern void sentry_init(IntPtr options); + [DllImport("sentry")] + private static extern SentryValueU sentry_value_new_object(); + + [DllImport("sentry")] + private static extern SentryValueU sentry_value_new_string(string value); + + [DllImport("sentry")] + private static extern SentryValueU sentry_value_new_breadcrumb(string? type, string? message); + + [DllImport("sentry")] + private static extern int sentry_value_set_by_key(SentryValueU value, string k, SentryValueU v); + + [DllImport("sentry")] + private static extern void sentry_add_breadcrumb(SentryValueU breadcrumb); + + [DllImport("sentry")] + private static extern void sentry_set_tag(string key, string value); + + [DllImport("sentry")] + private static extern void sentry_remove_tag(string key); + + [DllImport("sentry")] + private static extern void sentry_remove_user(); + /// /// Re-installs the sentry-native backend essentially retaking the signal handlers. /// @@ -67,5 +122,20 @@ public static void Init(SentryUnityOptions options) // Testing internal static Action ReinstallSentryNativeBackendStrategy = sentry_reinstall_backend; + + // native union sentry_value_u/t + [StructLayout(LayoutKind.Explicit)] + private struct SentryValueU + { + [FieldOffset(0)] + private ulong _bits; + [FieldOffset(0)] + private double _double; + } + + private static string GetTimestamp(DateTimeOffset timestamp) => + // "o": Using ISO 8601 to make sure the timestamp makes it to the bridge correctly. + // https://docs.microsoft.com/en-gb/dotnet/standard/base-types/standard-date-and-time-format-strings#Roundtrip + timestamp.ToString("o"); } } From 1151a53247585cee25644674c63418752e65d452 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos Date: Fri, 4 Feb 2022 15:58:31 +0100 Subject: [PATCH 2/5] refactor: extract ScopeObserver with the common code; finish the native implementation --- .../AndroidJavaScopeObserver.cs | 71 ++++---------- .../SentryNativeAndroid.cs | 3 +- .../NativeScopeObserver.cs | 59 ------------ src/Sentry.Unity.Native/SentryNative.cs | 2 +- src/Sentry.Unity.Native/SentryNativeBridge.cs | 51 ++++++---- .../IosNativeScopeObserver.cs | 56 ++--------- src/Sentry.Unity.iOS/SentryNativeIos.cs | 2 +- src/Sentry.Unity/IScopeObserver.cs | 43 +++++++++ src/Sentry.Unity/ScopeObserver.cs | 92 +++++++++++++++++++ 9 files changed, 199 insertions(+), 180 deletions(-) delete mode 100644 src/Sentry.Unity.Native/NativeScopeObserver.cs create mode 100644 src/Sentry.Unity/IScopeObserver.cs create mode 100644 src/Sentry.Unity/ScopeObserver.cs diff --git a/src/Sentry.Unity.Android/AndroidJavaScopeObserver.cs b/src/Sentry.Unity.Android/AndroidJavaScopeObserver.cs index 47796955e..f841561e3 100644 --- a/src/Sentry.Unity.Android/AndroidJavaScopeObserver.cs +++ b/src/Sentry.Unity.Android/AndroidJavaScopeObserver.cs @@ -1,5 +1,3 @@ -using Sentry.Extensibility; -using Sentry.Unity.Json; using UnityEngine; namespace Sentry.Unity.Android @@ -10,20 +8,11 @@ namespace Sentry.Unity.Android /// public class AndroidJavaScopeObserver : IScopeObserver { - private readonly SentryOptions _options; - - public AndroidJavaScopeObserver(SentryOptions options) => _options = options; - private AndroidJavaObject GetSentryJava() => new AndroidJavaClass("io.sentry.Sentry"); public void AddBreadcrumb(Breadcrumb breadcrumb) { AndroidJNI.AttachCurrentThread(); - - _options.DiagnosticLogger?.LogDebug("Android Scope Sync - Adding breadcrumb m:\"{0}\" l:\"{1}\"", - breadcrumb.Message, - breadcrumb.Level); - using var sentry = GetSentryJava(); using var javaBreadcrumb = new AndroidJavaObject("io.sentry.Breadcrumb"); javaBreadcrumb.Set("message", breadcrumb.Message); @@ -34,32 +23,21 @@ public void AddBreadcrumb(Breadcrumb breadcrumb) sentry.CallStatic("addBreadcrumb", javaBreadcrumb, null); } - public void SetExtra(string key, object? value) + public void SetExtra(string key, string value) { AndroidJNI.AttachCurrentThread(); + GetSentryJava().CallStatic("setExtra", key, value); + } - _options.DiagnosticLogger?.LogDebug("Android Scope Sync - Setting Extra k:\"{0}\" v:\"{1}\"", key, value); - - string? extraValue = null; - if (value is not null) - { - extraValue = SafeSerializer.SerializeSafely(value); - if (extraValue is null) - { - return; - } - } - - using var sentry = GetSentryJava(); - sentry.CallStatic("setExtra", key, extraValue); + public void UnsetExtra(string key) + { + AndroidJNI.AttachCurrentThread(); + GetSentryJava().CallStatic("setExtra", key, null); } public void SetTag(string key, string value) { AndroidJNI.AttachCurrentThread(); - - _options.DiagnosticLogger?.LogDebug("Android Scope Sync - Setting Tag k:\"{0}\" v:\"{1}\"", key, value); - using var sentry = GetSentryJava(); sentry.CallStatic("setTag", key, value); } @@ -67,43 +45,34 @@ public void SetTag(string key, string value) public void UnsetTag(string key) { AndroidJNI.AttachCurrentThread(); - - _options.DiagnosticLogger?.LogDebug("Android Scope Sync - Unsetting Tag k:\"{0}\"", key); - using var sentry = GetSentryJava(); sentry.CallStatic("removeTag", key); } - public void SetUser(User? user) + public void SetUser(User user) { AndroidJNI.AttachCurrentThread(); AndroidJavaObject? javaUser = null; try { - if (user is not null) - { - _options.DiagnosticLogger?.LogDebug("Android Scope Sync - Setting User i:\"{0}\" n:\"{1}\"", - user.Id, - user.Username); - - javaUser = new AndroidJavaObject("io.sentry.protocol.User"); - javaUser.Set("email", user.Email); - javaUser.Set("id", user.Id); - javaUser.Set("username", user.Username); - javaUser.Set("ipAddress", user.IpAddress); - } - else - { - _options.DiagnosticLogger?.LogDebug("Android Scope Sync - Unsetting User"); - } - using var sentry = GetSentryJava(); - sentry.CallStatic("setUser", javaUser); + javaUser = new AndroidJavaObject("io.sentry.protocol.User"); + javaUser.Set("email", user.Email); + javaUser.Set("id", user.Id); + javaUser.Set("username", user.Username); + javaUser.Set("ipAddress", user.IpAddress); + GetSentryJava().CallStatic("setUser", javaUser); } finally { javaUser?.Dispose(); } } + + public void UnsetUser() + { + AndroidJNI.AttachCurrentThread(); + GetSentryJava().CallStatic("setUser", null); + } } } diff --git a/src/Sentry.Unity.Android/SentryNativeAndroid.cs b/src/Sentry.Unity.Android/SentryNativeAndroid.cs index 9f2a563e0..457735e7e 100644 --- a/src/Sentry.Unity.Android/SentryNativeAndroid.cs +++ b/src/Sentry.Unity.Android/SentryNativeAndroid.cs @@ -1,5 +1,4 @@ using Sentry.Extensibility; -using UnityEngine; namespace Sentry.Unity.Android { @@ -16,7 +15,7 @@ public static void Configure(SentryUnityOptions options, ISentryUnityInfo sentry { if (options.AndroidNativeSupportEnabled) { - options.ScopeObserver = new AndroidJavaScopeObserver(options); + options.ScopeObserver = new ScopeObserver("Android", options, new AndroidJavaScopeObserver()); options.EnableScopeSync = true; options.CrashedLastRun = () => { diff --git a/src/Sentry.Unity.Native/NativeScopeObserver.cs b/src/Sentry.Unity.Native/NativeScopeObserver.cs deleted file mode 100644 index c6ff4bd5d..000000000 --- a/src/Sentry.Unity.Native/NativeScopeObserver.cs +++ /dev/null @@ -1,59 +0,0 @@ -using Sentry.Extensibility; -using Sentry.Unity.Json; -using UnityEngine; - -namespace Sentry.Unity.Native -{ - /// - /// Scope Observer for Native through P/Invoke. - /// - /// - public class NativeScopeObserver : IScopeObserver - { - private readonly SentryOptions _options; - - public NativeScopeObserver(SentryOptions options) => _options = options; - - public void AddBreadcrumb(Breadcrumb breadcrumb) - { - _options.DiagnosticLogger?.LogDebug("Native Scope Sync - Adding breadcrumb m:\"{0}\" l:\"{1}\"", - breadcrumb.Message, - breadcrumb.Level); - SentryNativeBridge.AddBreadcrumb(breadcrumb); - } - - public void SetExtra(string key, object? value) - { - _options.DiagnosticLogger?.LogDebug("Native Scope Sync - Setting Extra k:\"{0}\" v:\"{1}\"", key, value); - // TODO implement - } - - public void SetTag(string key, string value) - { - _options.DiagnosticLogger?.LogDebug("Native Scope Sync - Setting Tag k:\"{0}\" v:\"{1}\"", key, value); - // TODO implement - } - - public void UnsetTag(string key) - { - _options.DiagnosticLogger?.LogDebug("Native Scope Sync - Unsetting Tag k:\"{0}\"", key); - // TODO implement - } - - public void SetUser(User? user) - { - if (user is not null) - { - _options.DiagnosticLogger?.LogDebug("Native Scope Sync - Setting User i:\"{0}\" n:\"{1}\"", - user.Id, - user.Username); - // TODO implement - } - else - { - _options.DiagnosticLogger?.LogDebug("Native Scope Sync - Unsetting User"); - // TODO implement - } - } - } -} diff --git a/src/Sentry.Unity.Native/SentryNative.cs b/src/Sentry.Unity.Native/SentryNative.cs index 2e1cec61f..b2a047091 100644 --- a/src/Sentry.Unity.Native/SentryNative.cs +++ b/src/Sentry.Unity.Native/SentryNative.cs @@ -16,7 +16,7 @@ public static void Configure(SentryUnityOptions options) if (options.WindowsNativeSupportEnabled) { SentryNativeBridge.Init(options); - options.ScopeObserver = new NativeScopeObserver(options); + options.ScopeObserver = new ScopeObserver("Native", options, new SentryNativeBridge()); options.EnableScopeSync = true; // options.CrashedLastRun = () => // { diff --git a/src/Sentry.Unity.Native/SentryNativeBridge.cs b/src/Sentry.Unity.Native/SentryNativeBridge.cs index dbed963c4..1130f5b3c 100644 --- a/src/Sentry.Unity.Native/SentryNativeBridge.cs +++ b/src/Sentry.Unity.Native/SentryNativeBridge.cs @@ -14,7 +14,7 @@ namespace Sentry.Unity /// /// /// - public static class SentryNativeBridge + public class SentryNativeBridge : IScopeObserver { public static void Init(SentryUnityOptions options) { @@ -32,36 +32,36 @@ public static void Init(SentryUnityOptions options) sentry_init(cOptions); } - public static void AddBreadcrumb(Breadcrumb breadcrumb) + public void AddBreadcrumb(Breadcrumb breadcrumb) { // see https://develop.sentry.dev/sdk/event-payloads/breadcrumbs/ var crumb = sentry_value_new_breadcrumb(breadcrumb.Type, breadcrumb.Message); sentry_value_set_by_key(crumb, "level", sentry_value_new_string(breadcrumb.Level.ToString().ToLower())); sentry_value_set_by_key(crumb, "timestamp", sentry_value_new_string(GetTimestamp(breadcrumb.Timestamp))); - if (breadcrumb.Category is not null) - { - sentry_value_set_by_key(crumb, "category", sentry_value_new_string(breadcrumb.Category)); - } + nativeSetValueIfNotNull(crumb, "category", breadcrumb.Category); sentry_add_breadcrumb(crumb); } - public static void SetExtra(string key, string? value) - { - // TODO - } + public void SetExtra(string key, string value) => sentry_set_extra(key, sentry_value_new_string(value)); - public static void SetTag(string key, string value) => sentry_set_tag(key, value); + public void UnsetExtra(string key) => sentry_remove_extra(key); - public static void UnsetTag(string key) => sentry_remove_tag(key); + public void SetTag(string key, string value) => sentry_set_tag(key, value); - public static void SetUser(string? email, string? userId, string? ipAddress, string? username) + public void UnsetTag(string key) => sentry_remove_tag(key); + + public void SetUser(User user) { - var user = sentry_value_new_object(); - // TODO - sentry_set_user(user); + // see https://develop.sentry.dev/sdk/event-payloads/user/ + var cUser = sentry_value_new_object(); + nativeSetValueIfNotNull(cUser, "id", user.Id); + nativeSetValueIfNotNull(cUser, "username", user.Username); + nativeSetValueIfNotNull(cUser, "email", user.Email); + nativeSetValueIfNotNull(cUser, "ip_address", user.IpAddress); + sentry_set_user(cUser); } - public static void UnsetUser() => sentry_remove_user(); + public void UnsetUser() => sentry_remove_user(); // libsentry.so [DllImport("sentry")] @@ -92,6 +92,14 @@ public static void SetUser(string? email, string? userId, string? ipAddress, str [DllImport("sentry")] private static extern int sentry_value_set_by_key(SentryValueU value, string k, SentryValueU v); + private static void nativeSetValueIfNotNull(SentryValueU obj, string key, string? value) + { + if (value is not null) + { + sentry_value_set_by_key(obj, key, sentry_value_new_string(value)); + } + } + [DllImport("sentry")] private static extern void sentry_add_breadcrumb(SentryValueU breadcrumb); @@ -101,9 +109,18 @@ public static void SetUser(string? email, string? userId, string? ipAddress, str [DllImport("sentry")] private static extern void sentry_remove_tag(string key); + [DllImport("sentry")] + private static extern void sentry_set_user(SentryValueU user); + [DllImport("sentry")] private static extern void sentry_remove_user(); + [DllImport("sentry")] + private static extern void sentry_set_extra(string key, SentryValueU value); + + [DllImport("sentry")] + private static extern void sentry_remove_extra(string key); + /// /// Re-installs the sentry-native backend essentially retaking the signal handlers. /// diff --git a/src/Sentry.Unity.iOS/IosNativeScopeObserver.cs b/src/Sentry.Unity.iOS/IosNativeScopeObserver.cs index d58504306..b51418bf1 100644 --- a/src/Sentry.Unity.iOS/IosNativeScopeObserver.cs +++ b/src/Sentry.Unity.iOS/IosNativeScopeObserver.cs @@ -1,72 +1,30 @@ using System; -using Sentry.Extensibility; -using Sentry.Unity.Json; namespace Sentry.Unity.iOS { public class IosNativeScopeObserver : IScopeObserver { - private readonly SentryUnityOptions _options; - - public IosNativeScopeObserver(SentryUnityOptions options) => _options = options; - public void AddBreadcrumb(Breadcrumb breadcrumb) { - _options.DiagnosticLogger?.LogDebug("iOS Scope Sync - Adding breadcrumb m:\"{0}\" l:\"{1}\"", - breadcrumb.Message, - breadcrumb.Level); - var level = GetBreadcrumbLevel(breadcrumb.Level); var timestamp = GetTimestamp(breadcrumb.Timestamp); SentryCocoaBridgeProxy.SentryNativeBridgeAddBreadcrumb(timestamp, breadcrumb.Message, breadcrumb.Type, breadcrumb.Category, level); } - public void SetExtra(string key, object? value) - { - _options.DiagnosticLogger?.LogDebug("iOS Scope Sync - Setting Extra k:\"{0}\" v:\"{1}\"", key, value); + public void SetExtra(string key, string value) => SentryCocoaBridgeProxy.SentryNativeBridgeSetExtra(key, value); - string? extraValue = null; - if (value is not null) - { - extraValue = SafeSerializer.SerializeSafely(value); - if (extraValue is null) - { - return; - } - } + public void UnsetExtra(string key) => SentryCocoaBridgeProxy.SentryNativeBridgeSetExtra(key, null); - SentryCocoaBridgeProxy.SentryNativeBridgeSetExtra(key, extraValue); - } + public void SetTag(string key, string value) => SentryCocoaBridgeProxy.SentryNativeBridgeSetTag(key, value); - public void SetTag(string key, string value) - { - _options.DiagnosticLogger?.LogDebug("iOS Scope Sync - Setting Tag k:\"{0}\" v:\"{1}\"", key, value); - SentryCocoaBridgeProxy.SentryNativeBridgeSetTag(key, value); - } + public void UnsetTag(string key) => SentryCocoaBridgeProxy.SentryNativeBridgeUnsetTag(key); - public void UnsetTag(string key) - { - _options.DiagnosticLogger?.LogDebug("iOS Scope Sync - Unsetting Tag k:\"{0}\"", key); - SentryCocoaBridgeProxy.SentryNativeBridgeUnsetTag(key); - } + public void SetUser(User user) => + SentryCocoaBridgeProxy.SentryNativeBridgeSetUser(user.Email, user.Id, user.IpAddress, user.Username); - public void SetUser(User? user) - { - if (user is null) - { - _options.DiagnosticLogger?.LogDebug("iOS Scope Sync - Unsetting User"); + public void UnsetUser() => SentryCocoaBridgeProxy.SentryNativeBridgeUnsetUser(); - } - else - { - _options.DiagnosticLogger?.LogDebug("iOS Scope Sync - Setting User i:\"{0}\" n:\"{1}\"", - user.Id, - user.Username); - - SentryCocoaBridgeProxy.SentryNativeBridgeSetUser(user.Email, user.Id, user.IpAddress, user.Username); - } - } internal static string GetTimestamp(DateTimeOffset timestamp) => // "o": Using ISO 8601 to make sure the timestamp makes it to the bridge correctly. diff --git a/src/Sentry.Unity.iOS/SentryNativeIos.cs b/src/Sentry.Unity.iOS/SentryNativeIos.cs index 949a400da..828549ddf 100644 --- a/src/Sentry.Unity.iOS/SentryNativeIos.cs +++ b/src/Sentry.Unity.iOS/SentryNativeIos.cs @@ -15,7 +15,7 @@ public static void Configure(SentryUnityOptions options) { if (options.IosNativeSupportEnabled) { - options.ScopeObserver = new IosNativeScopeObserver(options); + options.ScopeObserver = new ScopeObserver("iOS", options, new IosNativeScopeObserver()); options.EnableScopeSync = true; options.CrashedLastRun = () => { diff --git a/src/Sentry.Unity/IScopeObserver.cs b/src/Sentry.Unity/IScopeObserver.cs new file mode 100644 index 000000000..847f8f5a2 --- /dev/null +++ b/src/Sentry.Unity/IScopeObserver.cs @@ -0,0 +1,43 @@ +namespace Sentry.Unity +{ + /// + /// Observer for the sync. of Scopes across SDKs. + /// + public interface IScopeObserver + { + /// + /// Adds a breadcrumb. + /// + void AddBreadcrumb(Breadcrumb breadcrumb); + + /// + /// Sets an extra. + /// + void SetExtra(string key, string value); + + /// + /// Remove an extra. + /// + void UnsetExtra(string key); + + /// + /// Sets a tag. + /// + void SetTag(string key, string value); + + /// + /// Removes a tag. + /// + void UnsetTag(string key); + + /// + /// Sets the user information. + /// + void SetUser(User user); + + /// + /// Sets the user information. + /// + void UnsetUser(); + } +} diff --git a/src/Sentry.Unity/ScopeObserver.cs b/src/Sentry.Unity/ScopeObserver.cs new file mode 100644 index 000000000..121c98f03 --- /dev/null +++ b/src/Sentry.Unity/ScopeObserver.cs @@ -0,0 +1,92 @@ +using Sentry.Extensibility; +using Sentry.Unity.Json; + +namespace Sentry.Unity +{ + /// + /// Sentry Unity Scope Observer wrapper for the common behaviour accross platforms. + /// + public class ScopeObserver : Sentry.IScopeObserver + { + private readonly SentryOptions _options; + private readonly Sentry.Unity.IScopeObserver _delegate; + private readonly string _name; + + public ScopeObserver( + string name, SentryOptions options, Sentry.Unity.IScopeObserver delegateObserver) + { + _name = name; + _options = options; + _delegate = delegateObserver; + } + + public void AddBreadcrumb(Breadcrumb breadcrumb) + { + _options.DiagnosticLogger?.Log(SentryLevel.Debug, + "{0} Scope Sync - Adding breadcrumb m:\"{1}\" l:\"{2}\"", null, _name, + breadcrumb.Message, breadcrumb.Level); + _delegate.AddBreadcrumb(breadcrumb); + } + + public void SetExtra(string key, object? value) + { + string? extraValue = null; + if (value is not null) + { + extraValue = SafeSerializer.SerializeSafely(value); + if (extraValue is null) + { + // TODO shouldn't we call UnsetExtra() instead? + _options.DiagnosticLogger?.Log(SentryLevel.Debug, + "{0} Scope Sync - ignoring SetExtra k:\"{1}\" v:\"{2}\" - value was serialized as null", + null, _name, key, value); + return; + } + } + + if (extraValue is null) + { + _options.DiagnosticLogger?.Log(SentryLevel.Debug, + "{0} Scope Sync - Unsetting Extra k:\"{1}\"", null, _name, key); + _delegate.UnsetExtra(key); + } + else + { + _options.DiagnosticLogger?.Log(SentryLevel.Debug, + "{0} Scope Sync - Setting Extra k:\"{1}\" v:\"{2}\"", null, _name, key, value); + _delegate.SetExtra(key, extraValue); + } + } + + public void SetTag(string key, string value) + { + _options.DiagnosticLogger?.Log(SentryLevel.Debug, + "{0} Scope Sync - Setting Tag k:\"{1}\" v:\"{2}\"", null, _name, key, value); + _delegate.SetTag(key, value); + } + + public void UnsetTag(string key) + { + _options.DiagnosticLogger?.Log( + SentryLevel.Debug, "{0} Scope Sync - Unsetting Tag k:\"{1}\"", null, _name, key); + _delegate.UnsetTag(key); + } + + public void SetUser(User? user) + { + if (user is not null) + { + _options.DiagnosticLogger?.Log(SentryLevel.Debug, + "{0} Scope Sync - Setting User i:\"{1}\" n:\"{2}\"", null, _name, user.Id, + user.Username); + _delegate.SetUser(user); + } + else + { + _options.DiagnosticLogger?.Log( + SentryLevel.Debug, "{0} Scope Sync - Unsetting User", null, _name); + _delegate.UnsetUser(); + } + } + } +} From 9b6063fa9f3fbe4c6cb9b8ad1dd85ce01d6b7185 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos Date: Fri, 4 Feb 2022 20:40:08 +0100 Subject: [PATCH 3/5] refactor: (vol 2) make ScopeObserver a base abstract class --- .../AndroidJavaScopeObserver.cs | 24 ++-- .../SentryNativeAndroid.cs | 2 +- .../NativeScopeObserver.cs | 104 ++++++++++++++++++ src/Sentry.Unity.Native/SentryNative.cs | 2 +- src/Sentry.Unity.Native/SentryNativeBridge.cs | 91 +-------------- .../IosNativeScopeObserver.cs | 20 ++-- src/Sentry.Unity.iOS/SentryNativeIos.cs | 2 +- src/Sentry.Unity/IScopeObserver.cs | 43 -------- src/Sentry.Unity/ScopeObserver.cs | 65 ++++++----- 9 files changed, 160 insertions(+), 193 deletions(-) create mode 100644 src/Sentry.Unity.Native/NativeScopeObserver.cs delete mode 100644 src/Sentry.Unity/IScopeObserver.cs diff --git a/src/Sentry.Unity.Android/AndroidJavaScopeObserver.cs b/src/Sentry.Unity.Android/AndroidJavaScopeObserver.cs index f841561e3..e8622f2f3 100644 --- a/src/Sentry.Unity.Android/AndroidJavaScopeObserver.cs +++ b/src/Sentry.Unity.Android/AndroidJavaScopeObserver.cs @@ -6,11 +6,14 @@ namespace Sentry.Unity.Android /// Scope Observer for Android through Java (JNI). /// /// - public class AndroidJavaScopeObserver : IScopeObserver + public class AndroidJavaScopeObserver : ScopeObserver { + public AndroidJavaScopeObserver(SentryOptions options) : base("Android", options) { } + + // TODO can we use a local var `AndroidJavaClass _sentryJava` initialized in a constructor instead? private AndroidJavaObject GetSentryJava() => new AndroidJavaClass("io.sentry.Sentry"); - public void AddBreadcrumb(Breadcrumb breadcrumb) + public override void AddBreadcrumbImpl(Breadcrumb breadcrumb) { AndroidJNI.AttachCurrentThread(); using var sentry = GetSentryJava(); @@ -23,33 +26,26 @@ public void AddBreadcrumb(Breadcrumb breadcrumb) sentry.CallStatic("addBreadcrumb", javaBreadcrumb, null); } - public void SetExtra(string key, string value) + public override void SetExtraImpl(string key, string? value) { AndroidJNI.AttachCurrentThread(); GetSentryJava().CallStatic("setExtra", key, value); } - - public void UnsetExtra(string key) - { - AndroidJNI.AttachCurrentThread(); - GetSentryJava().CallStatic("setExtra", key, null); - } - - public void SetTag(string key, string value) + public override void SetTagImpl(string key, string value) { AndroidJNI.AttachCurrentThread(); using var sentry = GetSentryJava(); sentry.CallStatic("setTag", key, value); } - public void UnsetTag(string key) + public override void UnsetTagImpl(string key) { AndroidJNI.AttachCurrentThread(); using var sentry = GetSentryJava(); sentry.CallStatic("removeTag", key); } - public void SetUser(User user) + public override void SetUserImpl(User user) { AndroidJNI.AttachCurrentThread(); @@ -69,7 +65,7 @@ public void SetUser(User user) } } - public void UnsetUser() + public override void UnsetUserImpl() { AndroidJNI.AttachCurrentThread(); GetSentryJava().CallStatic("setUser", null); diff --git a/src/Sentry.Unity.Android/SentryNativeAndroid.cs b/src/Sentry.Unity.Android/SentryNativeAndroid.cs index 457735e7e..59ce2d952 100644 --- a/src/Sentry.Unity.Android/SentryNativeAndroid.cs +++ b/src/Sentry.Unity.Android/SentryNativeAndroid.cs @@ -15,7 +15,7 @@ public static void Configure(SentryUnityOptions options, ISentryUnityInfo sentry { if (options.AndroidNativeSupportEnabled) { - options.ScopeObserver = new ScopeObserver("Android", options, new AndroidJavaScopeObserver()); + options.ScopeObserver = new AndroidJavaScopeObserver(options); options.EnableScopeSync = true; options.CrashedLastRun = () => { diff --git a/src/Sentry.Unity.Native/NativeScopeObserver.cs b/src/Sentry.Unity.Native/NativeScopeObserver.cs new file mode 100644 index 000000000..08d701c52 --- /dev/null +++ b/src/Sentry.Unity.Native/NativeScopeObserver.cs @@ -0,0 +1,104 @@ +using System; +using System.Runtime.InteropServices; +using Sentry.Extensibility; + +namespace Sentry.Unity +{ + /// + /// Scope Observer for Native through P/Invoke. + /// + /// + public class NativeScopeObserver : ScopeObserver + { + public NativeScopeObserver(SentryOptions options) : base("Native", options) { } + + public override void AddBreadcrumbImpl(Breadcrumb breadcrumb) + { + // see https://develop.sentry.dev/sdk/event-payloads/breadcrumbs/ + var crumb = sentry_value_new_breadcrumb(breadcrumb.Type, breadcrumb.Message); + sentry_value_set_by_key(crumb, "level", sentry_value_new_string(breadcrumb.Level.ToString().ToLower())); + sentry_value_set_by_key(crumb, "timestamp", sentry_value_new_string(GetTimestamp(breadcrumb.Timestamp))); + nativeSetValueIfNotNull(crumb, "category", breadcrumb.Category); + sentry_add_breadcrumb(crumb); + } + + public override void SetExtraImpl(string key, string? value) => + sentry_set_extra(key, value is null ? sentry_value_new_null() : sentry_value_new_string(value)); + + public override void SetTagImpl(string key, string value) => sentry_set_tag(key, value); + + public override void UnsetTagImpl(string key) => sentry_remove_tag(key); + + public override void SetUserImpl(User user) + { + // see https://develop.sentry.dev/sdk/event-payloads/user/ + var cUser = sentry_value_new_object(); + nativeSetValueIfNotNull(cUser, "id", user.Id); + nativeSetValueIfNotNull(cUser, "username", user.Username); + nativeSetValueIfNotNull(cUser, "email", user.Email); + nativeSetValueIfNotNull(cUser, "ip_address", user.IpAddress); + sentry_set_user(cUser); + } + + public override void UnsetUserImpl() => sentry_remove_user(); + + [DllImport("sentry")] + private static extern SentryValueU sentry_value_new_object(); + + [DllImport("sentry")] + private static extern SentryValueU sentry_value_new_null(); + + [DllImport("sentry")] + private static extern SentryValueU sentry_value_new_string(string value); + + [DllImport("sentry")] + private static extern SentryValueU sentry_value_new_breadcrumb(string? type, string? message); + + [DllImport("sentry")] + private static extern int sentry_value_set_by_key(SentryValueU value, string k, SentryValueU v); + + private static void nativeSetValueIfNotNull(SentryValueU obj, string key, string? value) + { + if (value is not null) + { + sentry_value_set_by_key(obj, key, sentry_value_new_string(value)); + } + } + + [DllImport("sentry")] + private static extern void sentry_add_breadcrumb(SentryValueU breadcrumb); + + [DllImport("sentry")] + private static extern void sentry_set_tag(string key, string value); + + [DllImport("sentry")] + private static extern void sentry_remove_tag(string key); + + [DllImport("sentry")] + private static extern void sentry_set_user(SentryValueU user); + + [DllImport("sentry")] + private static extern void sentry_remove_user(); + + [DllImport("sentry")] + private static extern void sentry_set_extra(string key, SentryValueU value); + + [DllImport("sentry")] + private static extern void sentry_remove_extra(string key); + + // native union sentry_value_u/t + [StructLayout(LayoutKind.Explicit)] + private struct SentryValueU + { + [FieldOffset(0)] + private ulong _bits; + [FieldOffset(0)] + private double _double; + } + + private static string GetTimestamp(DateTimeOffset timestamp) => + // "o": Using ISO 8601 to make sure the timestamp makes it to the bridge correctly. + // https://docs.microsoft.com/en-gb/dotnet/standard/base-types/standard-date-and-time-format-strings#Roundtrip + timestamp.ToString("o"); + } +} diff --git a/src/Sentry.Unity.Native/SentryNative.cs b/src/Sentry.Unity.Native/SentryNative.cs index b2a047091..2e1cec61f 100644 --- a/src/Sentry.Unity.Native/SentryNative.cs +++ b/src/Sentry.Unity.Native/SentryNative.cs @@ -16,7 +16,7 @@ public static void Configure(SentryUnityOptions options) if (options.WindowsNativeSupportEnabled) { SentryNativeBridge.Init(options); - options.ScopeObserver = new ScopeObserver("Native", options, new SentryNativeBridge()); + options.ScopeObserver = new NativeScopeObserver(options); options.EnableScopeSync = true; // options.CrashedLastRun = () => // { diff --git a/src/Sentry.Unity.Native/SentryNativeBridge.cs b/src/Sentry.Unity.Native/SentryNativeBridge.cs index 1130f5b3c..ada217e81 100644 --- a/src/Sentry.Unity.Native/SentryNativeBridge.cs +++ b/src/Sentry.Unity.Native/SentryNativeBridge.cs @@ -14,7 +14,7 @@ namespace Sentry.Unity /// /// /// - public class SentryNativeBridge : IScopeObserver + public static class SentryNativeBridge { public static void Init(SentryUnityOptions options) { @@ -32,37 +32,6 @@ public static void Init(SentryUnityOptions options) sentry_init(cOptions); } - public void AddBreadcrumb(Breadcrumb breadcrumb) - { - // see https://develop.sentry.dev/sdk/event-payloads/breadcrumbs/ - var crumb = sentry_value_new_breadcrumb(breadcrumb.Type, breadcrumb.Message); - sentry_value_set_by_key(crumb, "level", sentry_value_new_string(breadcrumb.Level.ToString().ToLower())); - sentry_value_set_by_key(crumb, "timestamp", sentry_value_new_string(GetTimestamp(breadcrumb.Timestamp))); - nativeSetValueIfNotNull(crumb, "category", breadcrumb.Category); - sentry_add_breadcrumb(crumb); - } - - public void SetExtra(string key, string value) => sentry_set_extra(key, sentry_value_new_string(value)); - - public void UnsetExtra(string key) => sentry_remove_extra(key); - - public void SetTag(string key, string value) => sentry_set_tag(key, value); - - public void UnsetTag(string key) => sentry_remove_tag(key); - - public void SetUser(User user) - { - // see https://develop.sentry.dev/sdk/event-payloads/user/ - var cUser = sentry_value_new_object(); - nativeSetValueIfNotNull(cUser, "id", user.Id); - nativeSetValueIfNotNull(cUser, "username", user.Username); - nativeSetValueIfNotNull(cUser, "email", user.Email); - nativeSetValueIfNotNull(cUser, "ip_address", user.IpAddress); - sentry_set_user(cUser); - } - - public void UnsetUser() => sentry_remove_user(); - // libsentry.so [DllImport("sentry")] private static extern IntPtr sentry_options_new(); @@ -80,47 +49,6 @@ public void SetUser(User user) [DllImport("sentry")] private static extern void sentry_init(IntPtr options); - [DllImport("sentry")] - private static extern SentryValueU sentry_value_new_object(); - - [DllImport("sentry")] - private static extern SentryValueU sentry_value_new_string(string value); - - [DllImport("sentry")] - private static extern SentryValueU sentry_value_new_breadcrumb(string? type, string? message); - - [DllImport("sentry")] - private static extern int sentry_value_set_by_key(SentryValueU value, string k, SentryValueU v); - - private static void nativeSetValueIfNotNull(SentryValueU obj, string key, string? value) - { - if (value is not null) - { - sentry_value_set_by_key(obj, key, sentry_value_new_string(value)); - } - } - - [DllImport("sentry")] - private static extern void sentry_add_breadcrumb(SentryValueU breadcrumb); - - [DllImport("sentry")] - private static extern void sentry_set_tag(string key, string value); - - [DllImport("sentry")] - private static extern void sentry_remove_tag(string key); - - [DllImport("sentry")] - private static extern void sentry_set_user(SentryValueU user); - - [DllImport("sentry")] - private static extern void sentry_remove_user(); - - [DllImport("sentry")] - private static extern void sentry_set_extra(string key, SentryValueU value); - - [DllImport("sentry")] - private static extern void sentry_remove_extra(string key); - /// /// Re-installs the sentry-native backend essentially retaking the signal handlers. /// @@ -139,20 +67,5 @@ private static void nativeSetValueIfNotNull(SentryValueU obj, string key, string // Testing internal static Action ReinstallSentryNativeBackendStrategy = sentry_reinstall_backend; - - // native union sentry_value_u/t - [StructLayout(LayoutKind.Explicit)] - private struct SentryValueU - { - [FieldOffset(0)] - private ulong _bits; - [FieldOffset(0)] - private double _double; - } - - private static string GetTimestamp(DateTimeOffset timestamp) => - // "o": Using ISO 8601 to make sure the timestamp makes it to the bridge correctly. - // https://docs.microsoft.com/en-gb/dotnet/standard/base-types/standard-date-and-time-format-strings#Roundtrip - timestamp.ToString("o"); } -} +} \ No newline at end of file diff --git a/src/Sentry.Unity.iOS/IosNativeScopeObserver.cs b/src/Sentry.Unity.iOS/IosNativeScopeObserver.cs index b51418bf1..87a5a5824 100644 --- a/src/Sentry.Unity.iOS/IosNativeScopeObserver.cs +++ b/src/Sentry.Unity.iOS/IosNativeScopeObserver.cs @@ -2,9 +2,11 @@ namespace Sentry.Unity.iOS { - public class IosNativeScopeObserver : IScopeObserver + public class IosNativeScopeObserver : ScopeObserver { - public void AddBreadcrumb(Breadcrumb breadcrumb) + public IosNativeScopeObserver(SentryOptions options) : base("iOS", options) { } + + public override void AddBreadcrumbImpl(Breadcrumb breadcrumb) { var level = GetBreadcrumbLevel(breadcrumb.Level); var timestamp = GetTimestamp(breadcrumb.Timestamp); @@ -12,19 +14,17 @@ public void AddBreadcrumb(Breadcrumb breadcrumb) SentryCocoaBridgeProxy.SentryNativeBridgeAddBreadcrumb(timestamp, breadcrumb.Message, breadcrumb.Type, breadcrumb.Category, level); } - public void SetExtra(string key, string value) => SentryCocoaBridgeProxy.SentryNativeBridgeSetExtra(key, value); - - public void UnsetExtra(string key) => SentryCocoaBridgeProxy.SentryNativeBridgeSetExtra(key, null); + public override void SetExtraImpl(string key, string? value) => + SentryCocoaBridgeProxy.SentryNativeBridgeSetExtra(key, value); - public void SetTag(string key, string value) => SentryCocoaBridgeProxy.SentryNativeBridgeSetTag(key, value); + public override void SetTagImpl(string key, string value) => SentryCocoaBridgeProxy.SentryNativeBridgeSetTag(key, value); - public void UnsetTag(string key) => SentryCocoaBridgeProxy.SentryNativeBridgeUnsetTag(key); + public override void UnsetTagImpl(string key) => SentryCocoaBridgeProxy.SentryNativeBridgeUnsetTag(key); - public void SetUser(User user) => + public override void SetUserImpl(User user) => SentryCocoaBridgeProxy.SentryNativeBridgeSetUser(user.Email, user.Id, user.IpAddress, user.Username); - public void UnsetUser() => - SentryCocoaBridgeProxy.SentryNativeBridgeUnsetUser(); + public override void UnsetUserImpl() => SentryCocoaBridgeProxy.SentryNativeBridgeUnsetUser(); internal static string GetTimestamp(DateTimeOffset timestamp) => // "o": Using ISO 8601 to make sure the timestamp makes it to the bridge correctly. diff --git a/src/Sentry.Unity.iOS/SentryNativeIos.cs b/src/Sentry.Unity.iOS/SentryNativeIos.cs index 828549ddf..949a400da 100644 --- a/src/Sentry.Unity.iOS/SentryNativeIos.cs +++ b/src/Sentry.Unity.iOS/SentryNativeIos.cs @@ -15,7 +15,7 @@ public static void Configure(SentryUnityOptions options) { if (options.IosNativeSupportEnabled) { - options.ScopeObserver = new ScopeObserver("iOS", options, new IosNativeScopeObserver()); + options.ScopeObserver = new IosNativeScopeObserver(options); options.EnableScopeSync = true; options.CrashedLastRun = () => { diff --git a/src/Sentry.Unity/IScopeObserver.cs b/src/Sentry.Unity/IScopeObserver.cs deleted file mode 100644 index 847f8f5a2..000000000 --- a/src/Sentry.Unity/IScopeObserver.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace Sentry.Unity -{ - /// - /// Observer for the sync. of Scopes across SDKs. - /// - public interface IScopeObserver - { - /// - /// Adds a breadcrumb. - /// - void AddBreadcrumb(Breadcrumb breadcrumb); - - /// - /// Sets an extra. - /// - void SetExtra(string key, string value); - - /// - /// Remove an extra. - /// - void UnsetExtra(string key); - - /// - /// Sets a tag. - /// - void SetTag(string key, string value); - - /// - /// Removes a tag. - /// - void UnsetTag(string key); - - /// - /// Sets the user information. - /// - void SetUser(User user); - - /// - /// Sets the user information. - /// - void UnsetUser(); - } -} diff --git a/src/Sentry.Unity/ScopeObserver.cs b/src/Sentry.Unity/ScopeObserver.cs index 121c98f03..46f040894 100644 --- a/src/Sentry.Unity/ScopeObserver.cs +++ b/src/Sentry.Unity/ScopeObserver.cs @@ -6,18 +6,16 @@ namespace Sentry.Unity /// /// Sentry Unity Scope Observer wrapper for the common behaviour accross platforms. /// - public class ScopeObserver : Sentry.IScopeObserver + public abstract class ScopeObserver : Sentry.IScopeObserver { private readonly SentryOptions _options; - private readonly Sentry.Unity.IScopeObserver _delegate; private readonly string _name; public ScopeObserver( - string name, SentryOptions options, Sentry.Unity.IScopeObserver delegateObserver) + string name, SentryOptions options) { _name = name; _options = options; - _delegate = delegateObserver; } public void AddBreadcrumb(Breadcrumb breadcrumb) @@ -25,68 +23,67 @@ public void AddBreadcrumb(Breadcrumb breadcrumb) _options.DiagnosticLogger?.Log(SentryLevel.Debug, "{0} Scope Sync - Adding breadcrumb m:\"{1}\" l:\"{2}\"", null, _name, breadcrumb.Message, breadcrumb.Level); - _delegate.AddBreadcrumb(breadcrumb); + AddBreadcrumbImpl(breadcrumb); } + public abstract void AddBreadcrumbImpl(Breadcrumb breadcrumb); + public void SetExtra(string key, object? value) { - string? extraValue = null; - if (value is not null) + var serialized = value is null ? null : SafeSerializer.SerializeSafely(value); + if (value is not null && serialized is null) { - extraValue = SafeSerializer.SerializeSafely(value); - if (extraValue is null) - { - // TODO shouldn't we call UnsetExtra() instead? - _options.DiagnosticLogger?.Log(SentryLevel.Debug, - "{0} Scope Sync - ignoring SetExtra k:\"{1}\" v:\"{2}\" - value was serialized as null", - null, _name, key, value); - return; - } - } - - if (extraValue is null) - { - _options.DiagnosticLogger?.Log(SentryLevel.Debug, - "{0} Scope Sync - Unsetting Extra k:\"{1}\"", null, _name, key); - _delegate.UnsetExtra(key); + _options.DiagnosticLogger?.Log(SentryLevel.Warning, + "{0} Scope Sync - SetExtra k:\"{1}\" v:\"{2}\" - value was serialized as null", + null, _name, key, value); } else { _options.DiagnosticLogger?.Log(SentryLevel.Debug, "{0} Scope Sync - Setting Extra k:\"{1}\" v:\"{2}\"", null, _name, key, value); - _delegate.SetExtra(key, extraValue); } + SetExtraImpl(key, serialized); } + public abstract void SetExtraImpl(string key, string? value); + public void SetTag(string key, string value) { _options.DiagnosticLogger?.Log(SentryLevel.Debug, "{0} Scope Sync - Setting Tag k:\"{1}\" v:\"{2}\"", null, _name, key, value); - _delegate.SetTag(key, value); + SetTagImpl(key, value); } + public abstract void SetTagImpl(string key, string value); + public void UnsetTag(string key) { _options.DiagnosticLogger?.Log( SentryLevel.Debug, "{0} Scope Sync - Unsetting Tag k:\"{1}\"", null, _name, key); - _delegate.UnsetTag(key); + UnsetTagImpl(key); } + public abstract void UnsetTagImpl(string key); + public void SetUser(User? user) { - if (user is not null) + if (user is null) { - _options.DiagnosticLogger?.Log(SentryLevel.Debug, - "{0} Scope Sync - Setting User i:\"{1}\" n:\"{2}\"", null, _name, user.Id, - user.Username); - _delegate.SetUser(user); + _options.DiagnosticLogger?.Log( + SentryLevel.Debug, "{0} Scope Sync - Unsetting User", null, _name); + UnsetUserImpl(); } else { - _options.DiagnosticLogger?.Log( - SentryLevel.Debug, "{0} Scope Sync - Unsetting User", null, _name); - _delegate.UnsetUser(); + _options.DiagnosticLogger?.Log(SentryLevel.Debug, + "{0} Scope Sync - Setting User i:\"{1}\" n:\"{2}\"", null, _name, user.Id, + user.Username); + SetUserImpl(user); } } + + public abstract void SetUserImpl(User user); + + public abstract void UnsetUserImpl(); } } From 4738c97544b2f5e71d9a1366cdea01813ef8025e Mon Sep 17 00:00:00 2001 From: Ivan Dlugos Date: Mon, 7 Feb 2022 19:06:16 +0100 Subject: [PATCH 4/5] fix: AndroidJavaScopeObserver regressions --- src/Sentry.Unity.Android/AndroidJavaScopeObserver.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Sentry.Unity.Android/AndroidJavaScopeObserver.cs b/src/Sentry.Unity.Android/AndroidJavaScopeObserver.cs index e8622f2f3..8ba6d2740 100644 --- a/src/Sentry.Unity.Android/AndroidJavaScopeObserver.cs +++ b/src/Sentry.Unity.Android/AndroidJavaScopeObserver.cs @@ -10,7 +10,6 @@ public class AndroidJavaScopeObserver : ScopeObserver { public AndroidJavaScopeObserver(SentryOptions options) : base("Android", options) { } - // TODO can we use a local var `AndroidJavaClass _sentryJava` initialized in a constructor instead? private AndroidJavaObject GetSentryJava() => new AndroidJavaClass("io.sentry.Sentry"); public override void AddBreadcrumbImpl(Breadcrumb breadcrumb) @@ -29,7 +28,8 @@ public override void AddBreadcrumbImpl(Breadcrumb breadcrumb) public override void SetExtraImpl(string key, string? value) { AndroidJNI.AttachCurrentThread(); - GetSentryJava().CallStatic("setExtra", key, value); + using var sentry = GetSentryJava(); + sentry.CallStatic("setExtra", key, value); } public override void SetTagImpl(string key, string value) { @@ -57,7 +57,8 @@ public override void SetUserImpl(User user) javaUser.Set("id", user.Id); javaUser.Set("username", user.Username); javaUser.Set("ipAddress", user.IpAddress); - GetSentryJava().CallStatic("setUser", javaUser); + using var sentry = GetSentryJava(); + sentry.CallStatic("setUser", javaUser); } finally { @@ -68,7 +69,8 @@ public override void SetUserImpl(User user) public override void UnsetUserImpl() { AndroidJNI.AttachCurrentThread(); - GetSentryJava().CallStatic("setUser", null); + using var sentry = GetSentryJava(); + sentry.CallStatic("setUser", null); } } } From 94479130c717936ffc494e3e51ddcba86e12cfe6 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos <6349682+vaind@users.noreply.github.com> Date: Mon, 7 Feb 2022 20:24:11 +0100 Subject: [PATCH 5/5] Update src/Sentry.Unity.Native/SentryNativeBridge.cs Co-authored-by: Bruno Garcia --- src/Sentry.Unity.Native/SentryNativeBridge.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sentry.Unity.Native/SentryNativeBridge.cs b/src/Sentry.Unity.Native/SentryNativeBridge.cs index ada217e81..47ba6502c 100644 --- a/src/Sentry.Unity.Native/SentryNativeBridge.cs +++ b/src/Sentry.Unity.Native/SentryNativeBridge.cs @@ -68,4 +68,4 @@ public static void Init(SentryUnityOptions options) // Testing internal static Action ReinstallSentryNativeBackendStrategy = sentry_reinstall_backend; } -} \ No newline at end of file +}