diff --git a/CHANGELOG.md b/CHANGELOG.md index ac18d06d0..a31d01397 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,16 +8,16 @@ ### Features +- The SDK now links errors and events (managed and native errors) via `trace ID`. This allows you to correlate events captured from different layers of your game ([#1997](https://github.com/getsentry/sentry-unity/pull/1997), [#2089](https://github.com/getsentry/sentry-unity/pull/2089), [#2106](https://github.com/getsentry/sentry-unity/pull/2106)) - Drastically improved performance of scope sync when targeting Android ([#2107](https://github.com/getsentry/sentry-unity/pull/2107)) -- When running on Android, Windows or Linux, the SDK now links errors and events originating on different layers (managed, native errors) via `trace ID` ([#1997](https://github.com/getsentry/sentry-unity/pull/1997), [#2089](https://github.com/getsentry/sentry-unity/pull/2089)) - The SDK now reports the game's name as part of the app context ([2083](https://github.com/getsentry/sentry-unity/pull/2083)) - The SDK now reports the active scene's name as part of the `Unity Context` ([2084](https://github.com/getsentry/sentry-unity/pull/2084)) ### Dependencies -- Bump Cocoa SDK from v8.45.0 to v8.49.0 ([#2063](https://github.com/getsentry/sentry-unity/pull/2063), [#2071](https://github.com/getsentry/sentry-unity/pull/2071), [#2105](https://github.com/getsentry/sentry-unity/pull/2105)) - - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8490) - - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.45.0...8.49.0) +- Bump Cocoa SDK from v8.45.0 to v8.49.1 ([#2063](https://github.com/getsentry/sentry-unity/pull/2063), [#2071](https://github.com/getsentry/sentry-unity/pull/2071), [#2105](https://github.com/getsentry/sentry-unity/pull/2105), [#2106](https://github.com/getsentry/sentry-unity/pull/2106)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8491) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.45.0...8.49.1) - Bump Java SDK from v8.3.0 to v8.8.0 ([#2066](https://github.com/getsentry/sentry-unity/pull/2066), [#2075](https://github.com/getsentry/sentry-unity/pull/2075), [#2092](https://github.com/getsentry/sentry-unity/pull/2092), [#2103](https://github.com/getsentry/sentry-unity/pull/2103), [#2111](https://github.com/getsentry/sentry-unity/pull/2111)) - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#880) - [diff](https://github.com/getsentry/sentry-java/compare/8.3.0...8.8.0) diff --git a/modules/sentry-cocoa.properties b/modules/sentry-cocoa.properties index 002085e06..52f92f3b6 100644 --- a/modules/sentry-cocoa.properties +++ b/modules/sentry-cocoa.properties @@ -1,2 +1,2 @@ -version = 8.49.0 +version = 8.49.1 repo = https://github.com/getsentry/sentry-cocoa diff --git a/package-dev/Plugins/iOS/SentryNativeBridge.m b/package-dev/Plugins/iOS/SentryNativeBridge.m index 98982997d..a609ce31a 100644 --- a/package-dev/Plugins/iOS/SentryNativeBridge.m +++ b/package-dev/Plugins/iOS/SentryNativeBridge.m @@ -169,6 +169,29 @@ void SentryNativeBridgeUnsetUser() return cString; } +void SentryNativeBridgeSetTrace(const char *traceId, const char *spanId) +{ + if (traceId == NULL || spanId == NULL) { + return; + } + + NSString *traceIdStr = [NSString stringWithUTF8String:traceId]; + NSString *spanIdStr = [NSString stringWithUTF8String:spanId]; + + // This is a workaround to deal with SentryId living inside the Swift header + Class sentryIdClass = NSClassFromString(@"_TtC6Sentry8SentryId"); + Class sentrySpanIdClass = NSClassFromString(@"SentrySpanId"); + + if (sentryIdClass && sentrySpanIdClass) { + id sentryTraceId = [[sentryIdClass alloc] initWithUUIDString:traceIdStr]; + id sentrySpanId = [[sentrySpanIdClass alloc] initWithValue:spanIdStr]; + + if (sentryTraceId && sentrySpanId) { + [PrivateSentrySDKOnly setTrace:sentryTraceId spanId:sentrySpanId]; + } + } +} + static inline NSString *_NSStringOrNil(const char *value) { return value ? [NSString stringWithUTF8String:value] : nil; diff --git a/package-dev/Plugins/iOS/SentryNativeBridgeNoOp.m b/package-dev/Plugins/iOS/SentryNativeBridgeNoOp.m index e9688495f..14f05c2c9 100644 --- a/package-dev/Plugins/iOS/SentryNativeBridgeNoOp.m +++ b/package-dev/Plugins/iOS/SentryNativeBridgeNoOp.m @@ -28,6 +28,8 @@ void SentryNativeBridgeUnsetUser() { } char *SentryNativeBridgeGetInstallationId() { return NULL; } +void SentryNativeBridgeSetTrace(const char *traceId, const char *spanId) { } + 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 9deca8dae..9bcc1e8f8 100644 --- a/package-dev/Plugins/macOS/SentryNativeBridge.m +++ b/package-dev/Plugins/macOS/SentryNativeBridge.m @@ -8,6 +8,8 @@ static Class SentryBreadcrumb; static Class SentryUser; static Class SentryOptions; +static Class SentryId; +static Class SentrySpanId; static Class PrivateSentrySDKOnly; #define LOAD_CLASS_OR_BREAK(name) \ @@ -17,6 +19,13 @@ break; \ } +#define LOAD_SWIFT_CLASS_OR_BREAK(name, mangled_name) \ + name = (__bridge Class)dlsym(dylib, "OBJC_CLASS_$_" #mangled_name); \ + if (!name) { \ + NSLog(@"Sentry (bridge): Couldn't load class '" #name "' from the dynamic library"); \ + break; \ + } + // Returns (bool): 0 on failure, 1 on success // WARNING: you may only call other Sentry* functions AFTER calling this AND only if it returned "1" int SentryNativeBridgeLoadLibrary() @@ -40,6 +49,8 @@ int SentryNativeBridgeLoadLibrary() LOAD_CLASS_OR_BREAK(SentryBreadcrumb) LOAD_CLASS_OR_BREAK(SentryUser) LOAD_CLASS_OR_BREAK(SentryOptions) + LOAD_SWIFT_CLASS_OR_BREAK(SentryId, _TtC6Sentry8SentryId) + LOAD_CLASS_OR_BREAK(SentrySpanId) LOAD_CLASS_OR_BREAK(PrivateSentrySDKOnly) // everything above passed - mark as successfully loaded @@ -263,6 +274,26 @@ void SentryNativeBridgeUnsetUser() return cString; } +void SentryNativeBridgeSetTrace(const char *traceId, const char *spanId) +{ + if (traceId == NULL || spanId == NULL) { + return; + } + + id sentryTraceId = [[SentryId alloc] + performSelector:@selector(initWithUUIDString:) + withObject:[NSString stringWithUTF8String:traceId]]; + + id sentrySpanId = [[SentrySpanId alloc] + performSelector:@selector(initWithValue:) + withObject:[NSString stringWithUTF8String:spanId]]; + + [PrivateSentrySDKOnly + performSelector:@selector(setTrace:spanId:) + withObject:sentryTraceId + withObject:sentrySpanId]; +} + static inline NSString *_NSStringOrNil(const char *value) { return value ? [NSString stringWithUTF8String:value] : nil; diff --git a/src/Sentry.Unity.iOS/NativeScopeObserver.cs b/src/Sentry.Unity.iOS/NativeScopeObserver.cs index 26aedced9..f5270c6bd 100644 --- a/src/Sentry.Unity.iOS/NativeScopeObserver.cs +++ b/src/Sentry.Unity.iOS/NativeScopeObserver.cs @@ -26,10 +26,8 @@ public override void SetUserImpl(SentryUser user) => public override void UnsetUserImpl() => SentryCocoaBridgeProxy.UnsetUser(); - public override void SetTraceImpl(SentryId traceId, SpanId spanId) - { - // TODO: Needs to be implemented - } + public override void SetTraceImpl(SentryId traceId, SpanId spanId) => + SentryCocoaBridgeProxy.SetTrace(traceId.ToString(), spanId.ToString()); 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/SentryCocoaBridgeProxy.cs b/src/Sentry.Unity.iOS/SentryCocoaBridgeProxy.cs index 7c8442c98..894a58652 100644 --- a/src/Sentry.Unity.iOS/SentryCocoaBridgeProxy.cs +++ b/src/Sentry.Unity.iOS/SentryCocoaBridgeProxy.cs @@ -108,4 +108,7 @@ public static bool Init(SentryUnityOptions options) [DllImport("__Internal", EntryPoint = "SentryNativeBridgeGetInstallationId")] public static extern string GetInstallationId(); + + [DllImport("__Internal", EntryPoint = "SentryNativeBridgeSetTrace")] + public static extern void SetTrace(string traceId, string spanId); }