diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ec36b573..4e93a89db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Fixes + +- The SDK now correctly synchronizes the `Environment` set on the `Scope` events coming from the native layer ([#2764](https://github.com/getsentry/sentry-unity/pull/2764)) + ### Dependencies - Bump .NET SDK from v6.5.0-33-g0140be0a to v6.7.0 ([#2761](https://github.com/getsentry/sentry-unity/pull/2761), [#2762](https://github.com/getsentry/sentry-unity/pull/2762)) diff --git a/package-dev/Plugins/Switch/sentry_native_stubs.c b/package-dev/Plugins/Switch/sentry_native_stubs.c index 041971be3..de334d36a 100644 --- a/package-dev/Plugins/Switch/sentry_native_stubs.c +++ b/package-dev/Plugins/Switch/sentry_native_stubs.c @@ -305,6 +305,11 @@ void sentry_set_trace(const char* trace_id, const char* parent_span_id) (void)parent_span_id; } +void sentry_set_environment(const char* environment) +{ + (void)environment; +} + /* * ============================================================================= * Crash Detection Functions diff --git a/package-dev/Plugins/iOS/SentryNativeBridge.m b/package-dev/Plugins/iOS/SentryNativeBridge.m index f9d643af3..62b7a5e4c 100644 --- a/package-dev/Plugins/iOS/SentryNativeBridge.m +++ b/package-dev/Plugins/iOS/SentryNativeBridge.m @@ -183,6 +183,15 @@ void SentryNativeBridgeSetTag(const char *key, const char *value) }]; } +void SentryNativeBridgeSetEnvironment(const char *environment) +{ + NSString *environmentString = _NSStringOrNil(environment); + + [SentrySDK configureScope:^(SentryScope *scope) { + [scope setEnvironment:environmentString]; + }]; +} + void SentryNativeBridgeUnsetTag(const char *key) { if (key == NULL) { diff --git a/package-dev/Plugins/iOS/SentryNativeBridgeNoOp.m b/package-dev/Plugins/iOS/SentryNativeBridgeNoOp.m index f9eab6e99..dc52c16e0 100644 --- a/package-dev/Plugins/iOS/SentryNativeBridgeNoOp.m +++ b/package-dev/Plugins/iOS/SentryNativeBridgeNoOp.m @@ -34,6 +34,8 @@ void SentryNativeBridgeUnsetUser() { } void SentryNativeBridgeSetTrace(const char *traceId, const char *spanId) { } +void SentryNativeBridgeSetEnvironment(const char *environment) { } + void SentryNativeBridgeWriteScope( // clang-format off // // const char *AppStartTime, // const char *AppBuildType, diff --git a/package-dev/Plugins/macOS/SentryNativeBridge.m b/package-dev/Plugins/macOS/SentryNativeBridge.m index 52270547f..3df39f4da 100644 --- a/package-dev/Plugins/macOS/SentryNativeBridge.m +++ b/package-dev/Plugins/macOS/SentryNativeBridge.m @@ -292,6 +292,15 @@ void SentryNativeBridgeSetTag(const char *key, const char *value) }); } +void SentryNativeBridgeSetEnvironment(const char *environment) +{ + NSString *environmentString = _NSStringOrNil(environment); + + SentryConfigureScope(^(id scope) { + [scope performSelector:@selector(setEnvironment:) withObject:environmentString]; + }); +} + void SentryNativeBridgeUnsetTag(const char *key) { if (key == NULL) { diff --git a/src/Sentry.Unity.Android/AndroidJavaScopeObserver.cs b/src/Sentry.Unity.Android/AndroidJavaScopeObserver.cs index 65936ac79..019e73081 100644 --- a/src/Sentry.Unity.Android/AndroidJavaScopeObserver.cs +++ b/src/Sentry.Unity.Android/AndroidJavaScopeObserver.cs @@ -37,6 +37,9 @@ public override void UnsetUserImpl() => public override void SetTraceImpl(SentryId traceId, SpanId spanId) => _sentryJava.SetTrace(traceId, spanId); + public override void SetEnvironmentImpl(string? environment) => + _sentryJava.SetEnvironment(environment); + public override void AddFileAttachmentImpl(string filePath, string fileName, string? contentType) => _sentryJava.AddAttachment(filePath, fileName, contentType); diff --git a/src/Sentry.Unity.Android/SentryJava.cs b/src/Sentry.Unity.Android/SentryJava.cs index 2f172083f..7726d343c 100644 --- a/src/Sentry.Unity.Android/SentryJava.cs +++ b/src/Sentry.Unity.Android/SentryJava.cs @@ -42,6 +42,7 @@ public void WriteScope( public void SetUser(SentryUser user); public void UnsetUser(); public void SetTrace(SentryId traceId, SpanId spanId); + public void SetEnvironment(string? environment); void AddAttachment(string path, string fileName, string? contentType); void AddAttachmentBytes(byte[] data, string fileName, string? contentType); void ClearAttachments(); @@ -387,6 +388,19 @@ public void SetTrace(SentryId traceId, SpanId spanId) }); } + public void SetEnvironment(string? environment) + { + // TODO: sentry-java lacks this API + // RunJniSafe(() => + // { + // using var sentry = GetSentryJava(); + // sentry.CallStatic("configureScope", new ScopeCallback(scope => + // { + // scope.Call("setEnvironment", environment); + // })); + // }); + } + public void AddAttachment(string path, string fileName, string? contentType) { RunJniSafe(() => diff --git a/src/Sentry.Unity.Native/CFunctions.cs b/src/Sentry.Unity.Native/CFunctions.cs index beb991ca9..e0bef2db9 100644 --- a/src/Sentry.Unity.Native/CFunctions.cs +++ b/src/Sentry.Unity.Native/CFunctions.cs @@ -165,6 +165,9 @@ internal static void SetValueIfNotNull(sentry_value_t obj, string key, long? val [DllImport(SentryLib)] internal static extern void sentry_set_trace(string traceId, string parentSpanId); + [DllImport(SentryLib)] + internal static extern void sentry_set_environment(string? environment); + [DllImport(SentryLib)] internal static extern IntPtr sentry_attach_file(string path); diff --git a/src/Sentry.Unity.Native/NativeScopeObserver.cs b/src/Sentry.Unity.Native/NativeScopeObserver.cs index 28fe9c84e..001655f67 100644 --- a/src/Sentry.Unity.Native/NativeScopeObserver.cs +++ b/src/Sentry.Unity.Native/NativeScopeObserver.cs @@ -52,6 +52,9 @@ public override void SetUserImpl(SentryUser user) public override void SetTraceImpl(SentryId traceId, SpanId spanId) => C.sentry_set_trace(traceId.ToString(), spanId.ToString()); + public override void SetEnvironmentImpl(string? environment) => + C.sentry_set_environment(environment); + public override void AddFileAttachmentImpl(string filePath, string fileName, string? contentType) => C.sentry_attach_file(filePath); diff --git a/src/Sentry.Unity.iOS/NativeScopeObserver.cs b/src/Sentry.Unity.iOS/NativeScopeObserver.cs index 1bedc6b92..393ee19ef 100644 --- a/src/Sentry.Unity.iOS/NativeScopeObserver.cs +++ b/src/Sentry.Unity.iOS/NativeScopeObserver.cs @@ -55,6 +55,9 @@ public override void SetUserImpl(SentryUser user) => public override void SetTraceImpl(SentryId traceId, SpanId spanId) => SentryCocoaBridgeProxy.SetTrace(traceId.ToString(), spanId.ToString()); + public override void SetEnvironmentImpl(string? environment) => + SentryCocoaBridgeProxy.SetEnvironment(environment); + public override void AddFileAttachmentImpl(string filePath, string fileName, string? contentType) { // iOS/macOS attachment sync to sentry-cocoa is not yet supported. diff --git a/src/Sentry.Unity.iOS/SentryCocoaBridgeProxy.cs b/src/Sentry.Unity.iOS/SentryCocoaBridgeProxy.cs index 70055b56e..23adb1c87 100644 --- a/src/Sentry.Unity.iOS/SentryCocoaBridgeProxy.cs +++ b/src/Sentry.Unity.iOS/SentryCocoaBridgeProxy.cs @@ -151,4 +151,7 @@ public static extern void AddBreadcrumb(string timestamp, string? message, strin [DllImport("__Internal", EntryPoint = "SentryNativeBridgeSetTrace")] public static extern void SetTrace(string traceId, string spanId); + + [DllImport("__Internal", EntryPoint = "SentryNativeBridgeSetEnvironment")] + public static extern void SetEnvironment(string? environment); } diff --git a/src/Sentry.Unity/ScopeObserver.cs b/src/Sentry.Unity/ScopeObserver.cs index 3ae361163..a1a789ce4 100644 --- a/src/Sentry.Unity/ScopeObserver.cs +++ b/src/Sentry.Unity/ScopeObserver.cs @@ -87,6 +87,14 @@ public void SetTrace(SentryId traceId, SpanId spanId) public abstract void SetTraceImpl(SentryId traceId, SpanId spanId); + public void SetEnvironment(string? environment) + { + _options.LogDebug("{0} Scope Sync - Setting Environment e:\"{1}\"", _name, environment); + SetEnvironmentImpl(environment); + } + + public abstract void SetEnvironmentImpl(string? environment); + public void AddAttachment(SentryAttachment attachment) { if (attachment.Content is FileAttachmentContent fileContent) diff --git a/src/sentry-dotnet b/src/sentry-dotnet index 4385deaaf..b6315ad2e 160000 --- a/src/sentry-dotnet +++ b/src/sentry-dotnet @@ -1 +1 @@ -Subproject commit 4385deaafa1091e2e6b69862b5941c381549d493 +Subproject commit b6315ad2e98e22597f79f422b00d8b3970d1cec9 diff --git a/test/Sentry.Unity.Android.Tests/TestSentryJava.cs b/test/Sentry.Unity.Android.Tests/TestSentryJava.cs index 195d94221..84c7f3735 100644 --- a/test/Sentry.Unity.Android.Tests/TestSentryJava.cs +++ b/test/Sentry.Unity.Android.Tests/TestSentryJava.cs @@ -55,6 +55,8 @@ public void UnsetUser() { } public void SetTrace(SentryId traceId, SpanId spanId) { } + public void SetEnvironment(string? environment) { } + public void AddAttachment(string path, string fileName, string? contentType) { } public void AddAttachmentBytes(byte[] data, string fileName, string? contentType) { } diff --git a/test/Sentry.Unity.Tests/UnityEventScopeTests.cs b/test/Sentry.Unity.Tests/UnityEventScopeTests.cs index 2bf8103d5..b9d341745 100644 --- a/test/Sentry.Unity.Tests/UnityEventScopeTests.cs +++ b/test/Sentry.Unity.Tests/UnityEventScopeTests.cs @@ -422,6 +422,56 @@ public void UserId_ScopeSync_TriggeredEvenWhenUserAlreadySet() Assert.AreEqual("native-id", observer.LastUser!.Id); } + [Test] + public void Environment_ScopeSync_ForwardedToObserver() + { + // arrange - enable scope sync with a tracking observer + var options = new SentryUnityOptions(application: _testApplication); + var observer = new TestScopeObserver(options); + options.ScopeObserver = observer; + options.EnableScopeSync = true; + + var scope = new Scope(options); + + // act + scope.Environment = "the-environment"; + + // assert + Assert.AreEqual("the-environment", observer.LastEnvironment); + } + + [Test] + public void Environment_ScopeSyncDisabled_NotForwardedToObserver() + { + // arrange + var options = new SentryUnityOptions(application: _testApplication); + var observer = new TestScopeObserver(options); + options.ScopeObserver = observer; + options.EnableScopeSync = false; + + var scope = new Scope(options); + + // act + scope.Environment = "the-environment"; + + // assert + Assert.IsNull(observer.LastEnvironment); + } + + [Test] + public void SetEnvironment_DelegatesToImpl() + { + // arrange + var options = new SentryUnityOptions(application: _testApplication); + var observer = new TestScopeObserver(options); + + // act + observer.SetEnvironment("the-environment"); + + // assert + Assert.AreEqual("the-environment", observer.LastEnvironment); + } + [Test] public void OperatingSystemProtocol_Assigned() { @@ -668,6 +718,7 @@ internal sealed class TestSentrySystemInfo : ISentrySystemInfo internal sealed class TestScopeObserver : ScopeObserver { public SentryUser? LastUser { get; set; } + public string? LastEnvironment { get; set; } public TestScopeObserver(SentryOptions options) : base("Test", options) { } @@ -678,6 +729,7 @@ public override void UnsetTagImpl(string key) { } public override void SetUserImpl(SentryUser user) => LastUser = user; public override void UnsetUserImpl() => LastUser = null; public override void SetTraceImpl(SentryId traceId, SpanId spanId) { } + public override void SetEnvironmentImpl(string? environment) => LastEnvironment = environment; public override void AddFileAttachmentImpl(string filePath, string fileName, string? contentType) { } public override void AddByteAttachmentImpl(byte[] data, string fileName, string? contentType) { } public override void ClearAttachmentsImpl() { }