From 90c07d2a7c008086618d1c624b159db01c133aa0 Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Mon, 23 Dec 2024 15:58:59 +0100 Subject: [PATCH 01/15] Added native information to session replay options event --- Sources/Sentry/SentryMeta.m | 22 +++++++++++++++++-- Sources/Sentry/include/SentryMeta.h | 15 +++++++++++++ Sources/Sentry/include/SentryPrivate.h | 1 + .../RRWeb/SentryRRWebOptionsEvent.swift | 4 +++- .../SentrySessionReplayTests.swift | 2 ++ 5 files changed, 41 insertions(+), 3 deletions(-) diff --git a/Sources/Sentry/SentryMeta.m b/Sources/Sentry/SentryMeta.m index e76a7f0261c..97117309b4f 100644 --- a/Sources/Sentry/SentryMeta.m +++ b/Sources/Sentry/SentryMeta.m @@ -2,11 +2,20 @@ @implementation SentryMeta + +const NSString * const sentryVersionString = @"8.43.0-beta.1"; +const NSString * const sentrySdkName = @"sentry.cocoa"; + // Don't remove the static keyword. If you do the compiler adds the constant name to the global // symbol table and it might clash with other constants. When keeping the static keyword the // compiler replaces all occurrences with the value. -static NSString *versionString = @"8.43.0-beta.1"; -static NSString *sdkName = @"sentry.cocoa"; +static NSString *versionString; +static NSString *sdkName; + ++ (void)initialize { + versionString = sentryVersionString.copy; + sdkName = sentrySdkName.copy; +} + (NSString *)versionString { @@ -28,4 +37,13 @@ + (void)setSdkName:(NSString *)value sdkName = value; } ++ (NSString*)nativeSdkName { + return sentrySdkName.copy; +} + ++ (NSString*)nativeVersionString { + return sentryVersionString.copy; +} + + @end diff --git a/Sources/Sentry/include/SentryMeta.h b/Sources/Sentry/include/SentryMeta.h index 3ee7fd9efc4..916ac62e4c0 100644 --- a/Sources/Sentry/include/SentryMeta.h +++ b/Sources/Sentry/include/SentryMeta.h @@ -14,6 +14,21 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, class, copy) NSString *sdkName; +/** + * Return a version string e.g: 1.2.3 (3) + * This always report the version of Sentry.cocoa, + * `versionString` can be changed by hybrid SDKs. + * We can use this property to get which version of Sentry cocoa + * the hybrid SDK is using. + */ +@property (nonatomic, class, readonly) NSString *nativeVersionString; + +/** + * Returns "sentry.cocoa" + * `sdkName` can be changed by hybrid SDKs. + */ +@property (nonatomic, class, readonly) NSString *nativeSdkName; + @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryPrivate.h b/Sources/Sentry/include/SentryPrivate.h index 27c7ad8d640..e4143c11e78 100644 --- a/Sources/Sentry/include/SentryPrivate.h +++ b/Sources/Sentry/include/SentryPrivate.h @@ -16,3 +16,4 @@ #import "SentryRandom.h" #import "SentrySdkInfo.h" #import "SentrySession.h" +#import "SentryMeta.h" diff --git a/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebOptionsEvent.swift b/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebOptionsEvent.swift index 51ac516535b..a483818b64a 100644 --- a/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebOptionsEvent.swift +++ b/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebOptionsEvent.swift @@ -12,7 +12,9 @@ import Foundation "maskAllImages": options.maskAllImages, "quality": String(describing: options.quality), "maskedViewClasses": options.maskedViewClasses.map(String.init(describing: )).joined(separator: ", "), - "unmaskedViewClasses": options.unmaskedViewClasses.map(String.init(describing: )).joined(separator: ", ") + "unmaskedViewClasses": options.unmaskedViewClasses.map(String.init(describing: )).joined(separator: ", "), + "nativeSdkName": SentryMeta.nativeSdkName, + "nativeSdkVersion": SentryMeta.nativeVersionString, ] ) } diff --git a/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayTests.swift b/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayTests.swift index 68377c17a0a..e3910c22c6a 100644 --- a/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayTests.swift +++ b/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayTests.swift @@ -428,6 +428,8 @@ class SentrySessionReplayTests: XCTestCase { XCTAssertEqual(options["maskedViewClasses"] as? String, "") XCTAssertEqual(options["unmaskedViewClasses"] as? String, "") XCTAssertEqual(options["quality"] as? String, "medium") + XCTAssertEqual(options["nativeSdkName"] as? String, SentryMeta.nativeSdkName) + XCTAssertEqual(options["nativeSdkVersion"] as? String, SentryMeta.nativeVersionString) } func testOptionsInTheEventAllChanged() throws { From ec45856c295275ee1c3c6bedb5372132f80f14ce Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Mon, 23 Dec 2024 16:00:12 +0100 Subject: [PATCH 02/15] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cefaea27cbb..33958c2a4df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Improvements + +- Add native SDK information in the replay option event () + ## 8.43.0-beta.1 ### Improvements From 9f3b6e04267c066066c6f8a1d79b70b8a0bc3141 Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Mon, 23 Dec 2024 16:01:59 +0100 Subject: [PATCH 03/15] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33958c2a4df..5a5f555f2b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Improvements -- Add native SDK information in the replay option event () +- Add native SDK information in the replay option event (#4663) ## 8.43.0-beta.1 From ce938466ee223d5930c6043b5d48fb70ae91b4d7 Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Mon, 23 Dec 2024 15:02:38 +0000 Subject: [PATCH 04/15] Format code --- Sources/Sentry/SentryMeta.m | 15 ++++++++------- Sources/Sentry/include/SentryPrivate.h | 2 +- .../RRWeb/SentryRRWebOptionsEvent.swift | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Sources/Sentry/SentryMeta.m b/Sources/Sentry/SentryMeta.m index 97117309b4f..eb4cacb9560 100644 --- a/Sources/Sentry/SentryMeta.m +++ b/Sources/Sentry/SentryMeta.m @@ -2,9 +2,8 @@ @implementation SentryMeta - -const NSString * const sentryVersionString = @"8.43.0-beta.1"; -const NSString * const sentrySdkName = @"sentry.cocoa"; +const NSString *const sentryVersionString = @"8.43.0-beta.1"; +const NSString *const sentrySdkName = @"sentry.cocoa"; // Don't remove the static keyword. If you do the compiler adds the constant name to the global // symbol table and it might clash with other constants. When keeping the static keyword the @@ -12,7 +11,8 @@ @implementation SentryMeta static NSString *versionString; static NSString *sdkName; -+ (void)initialize { ++ (void)initialize +{ versionString = sentryVersionString.copy; sdkName = sentrySdkName.copy; } @@ -37,13 +37,14 @@ + (void)setSdkName:(NSString *)value sdkName = value; } -+ (NSString*)nativeSdkName { ++ (NSString *)nativeSdkName +{ return sentrySdkName.copy; } -+ (NSString*)nativeVersionString { ++ (NSString *)nativeVersionString +{ return sentryVersionString.copy; } - @end diff --git a/Sources/Sentry/include/SentryPrivate.h b/Sources/Sentry/include/SentryPrivate.h index e4143c11e78..c1415fe1481 100644 --- a/Sources/Sentry/include/SentryPrivate.h +++ b/Sources/Sentry/include/SentryPrivate.h @@ -13,7 +13,7 @@ #import "SentryDisplayLinkWrapper.h" #import "SentryLevelHelper.h" #import "SentryLogC.h" +#import "SentryMeta.h" #import "SentryRandom.h" #import "SentrySdkInfo.h" #import "SentrySession.h" -#import "SentryMeta.h" diff --git a/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebOptionsEvent.swift b/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebOptionsEvent.swift index a483818b64a..90685638bcc 100644 --- a/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebOptionsEvent.swift +++ b/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebOptionsEvent.swift @@ -14,7 +14,7 @@ import Foundation "maskedViewClasses": options.maskedViewClasses.map(String.init(describing: )).joined(separator: ", "), "unmaskedViewClasses": options.unmaskedViewClasses.map(String.init(describing: )).joined(separator: ", "), "nativeSdkName": SentryMeta.nativeSdkName, - "nativeSdkVersion": SentryMeta.nativeVersionString, + "nativeSdkVersion": SentryMeta.nativeVersionString ] ) } From 626045de29061c2200669ce4a27161b7006bf420 Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Mon, 23 Dec 2024 16:43:18 +0100 Subject: [PATCH 05/15] change sdk for SR --- Sources/Sentry/PrivateSentrySDKOnly.mm | 4 ++++ Sources/Sentry/SentrySessionReplayIntegration.m | 4 +++- .../Sentry/include/HybridPublic/PrivateSentrySDKOnly.h | 1 + .../include/SentrySessionReplayIntegration+Private.h | 8 +++++++- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Sources/Sentry/PrivateSentrySDKOnly.mm b/Sources/Sentry/PrivateSentrySDKOnly.mm index 086876a5bc6..5d17ae937f8 100644 --- a/Sources/Sentry/PrivateSentrySDKOnly.mm +++ b/Sources/Sentry/PrivateSentrySDKOnly.mm @@ -379,6 +379,10 @@ + (void)setRedactContainerClass:(Class _Nonnull)containerClass setRedactContainerClass:containerClass]; } ++ (void)setReplaySdkInfo:(NSDictionary *)sdkInfo { + [PrivateSentrySDKOnly getReplayIntegration].sdkInfo = sdkInfo; +} + #endif @end diff --git a/Sources/Sentry/SentrySessionReplayIntegration.m b/Sources/Sentry/SentrySessionReplayIntegration.m index 92a2b7785de..713d3828d7d 100644 --- a/Sources/Sentry/SentrySessionReplayIntegration.m +++ b/Sources/Sentry/SentrySessionReplayIntegration.m @@ -581,7 +581,9 @@ - (void)sessionReplayNewSegmentWithReplayEvent:(SentryReplayEvent *)replayEvent [self stop]; return; } - + + replayEvent.sdk = self.sdkInfo; + [SentrySDK.currentHub captureReplayEvent:replayEvent replayRecording:replayRecording video:videoUrl]; diff --git a/Sources/Sentry/include/HybridPublic/PrivateSentrySDKOnly.h b/Sources/Sentry/include/HybridPublic/PrivateSentrySDKOnly.h index 44f48264b83..10807152cf9 100644 --- a/Sources/Sentry/include/HybridPublic/PrivateSentrySDKOnly.h +++ b/Sources/Sentry/include/HybridPublic/PrivateSentrySDKOnly.h @@ -198,6 +198,7 @@ typedef void (^SentryOnAppStartMeasurementAvailable)( + (void)addReplayRedactClasses:(NSArray *_Nonnull)classes; + (void)setIgnoreContainerClass:(Class _Nonnull)containerClass; + (void)setRedactContainerClass:(Class _Nonnull)containerClass; ++ (void)setReplaySdkInfo:(NSDictionary *)sdkInfo; #endif + (nullable NSDictionary *)appStartMeasurementWithSpans; diff --git a/Sources/Sentry/include/SentrySessionReplayIntegration+Private.h b/Sources/Sentry/include/SentrySessionReplayIntegration+Private.h index b9d45561020..1fe037a93ad 100644 --- a/Sources/Sentry/include/SentrySessionReplayIntegration+Private.h +++ b/Sources/Sentry/include/SentrySessionReplayIntegration+Private.h @@ -4,16 +4,22 @@ #if SENTRY_TARGET_REPLAY_SUPPORTED +NS_ASSUME_NONNULL_BEGIN + @class SentrySessionReplay; @class SentryViewPhotographer; @interface SentrySessionReplayIntegration () -@property (nonatomic, strong) SentrySessionReplay *sessionReplay; +@property (nonatomic, strong, nullable) SentrySessionReplay *sessionReplay; @property (nonatomic, strong) SentryViewPhotographer *viewPhotographer; +@property (nonatomic, strong, nullable) NSDictionary *sdkInfo; + @end +NS_ASSUME_NONNULL_END + #endif From da5b308e5a73a91856178a3bc7e98bb170ebb271 Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Mon, 23 Dec 2024 15:44:32 +0000 Subject: [PATCH 06/15] Format code --- Sources/Sentry/PrivateSentrySDKOnly.mm | 3 ++- Sources/Sentry/SentrySessionReplayIntegration.m | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Sources/Sentry/PrivateSentrySDKOnly.mm b/Sources/Sentry/PrivateSentrySDKOnly.mm index 5d17ae937f8..267f84175de 100644 --- a/Sources/Sentry/PrivateSentrySDKOnly.mm +++ b/Sources/Sentry/PrivateSentrySDKOnly.mm @@ -379,7 +379,8 @@ + (void)setRedactContainerClass:(Class _Nonnull)containerClass setRedactContainerClass:containerClass]; } -+ (void)setReplaySdkInfo:(NSDictionary *)sdkInfo { ++ (void)setReplaySdkInfo:(NSDictionary *)sdkInfo +{ [PrivateSentrySDKOnly getReplayIntegration].sdkInfo = sdkInfo; } diff --git a/Sources/Sentry/SentrySessionReplayIntegration.m b/Sources/Sentry/SentrySessionReplayIntegration.m index 713d3828d7d..df717f56956 100644 --- a/Sources/Sentry/SentrySessionReplayIntegration.m +++ b/Sources/Sentry/SentrySessionReplayIntegration.m @@ -581,9 +581,9 @@ - (void)sessionReplayNewSegmentWithReplayEvent:(SentryReplayEvent *)replayEvent [self stop]; return; } - + replayEvent.sdk = self.sdkInfo; - + [SentrySDK.currentHub captureReplayEvent:replayEvent replayRecording:replayRecording video:videoUrl]; From 5fb20ad8be1e89e34be069758d03d0710f5c70f0 Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Tue, 24 Dec 2024 09:25:38 +0100 Subject: [PATCH 07/15] move sdk info to replayoptions --- Sources/Sentry/PrivateSentrySDKOnly.mm | 4 ---- Sources/Sentry/SentrySessionReplayIntegration.m | 7 +++++-- Sources/Sentry/include/HybridPublic/PrivateSentrySDKOnly.h | 1 - .../include/SentrySessionReplayIntegration+Private.h | 2 -- .../Integrations/SessionReplay/SentryReplayOptions.swift | 6 ++++++ 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Sources/Sentry/PrivateSentrySDKOnly.mm b/Sources/Sentry/PrivateSentrySDKOnly.mm index 5d17ae937f8..086876a5bc6 100644 --- a/Sources/Sentry/PrivateSentrySDKOnly.mm +++ b/Sources/Sentry/PrivateSentrySDKOnly.mm @@ -379,10 +379,6 @@ + (void)setRedactContainerClass:(Class _Nonnull)containerClass setRedactContainerClass:containerClass]; } -+ (void)setReplaySdkInfo:(NSDictionary *)sdkInfo { - [PrivateSentrySDKOnly getReplayIntegration].sdkInfo = sdkInfo; -} - #endif @end diff --git a/Sources/Sentry/SentrySessionReplayIntegration.m b/Sources/Sentry/SentrySessionReplayIntegration.m index 713d3828d7d..20cf046da44 100644 --- a/Sources/Sentry/SentrySessionReplayIntegration.m +++ b/Sources/Sentry/SentrySessionReplayIntegration.m @@ -24,6 +24,7 @@ # import "SentrySwizzle.h" # import "SentryUIApplication.h" # import +# import "SentrySdkInfo.h" NS_ASSUME_NONNULL_BEGIN @@ -50,6 +51,7 @@ @implementation SentrySessionReplayIntegration { id _rateLimits; id _currentScreenshotProvider; id _currentBreadcrumbConverter; + NSDictionary *_sdkInfo; // We need to use this variable to identify whether rate limiting was ever activated for session // replay in this session, instead of always looking for the rate status in `SentryRateLimits` // This is the easiest way to ensure segment 0 will always reach the server, because session @@ -88,7 +90,8 @@ - (void)setupWith:(SentryReplayOptions *)replayOptions enableTouchTracker:(BOOL) _replayOptions = replayOptions; _viewPhotographer = [[SentryViewPhotographer alloc] initWithRedactOptions:replayOptions]; _rateLimits = SentryDependencyContainer.sharedInstance.rateLimits; - + _sdkInfo = replayOptions.sdkInfo; + if (touchTracker) { _touchTracker = [[SentryTouchTracker alloc] initWithDateProvider:SentryDependencyContainer.sharedInstance.dateProvider @@ -582,7 +585,7 @@ - (void)sessionReplayNewSegmentWithReplayEvent:(SentryReplayEvent *)replayEvent return; } - replayEvent.sdk = self.sdkInfo; + replayEvent.sdk = _sdkInfo; [SentrySDK.currentHub captureReplayEvent:replayEvent replayRecording:replayRecording diff --git a/Sources/Sentry/include/HybridPublic/PrivateSentrySDKOnly.h b/Sources/Sentry/include/HybridPublic/PrivateSentrySDKOnly.h index 10807152cf9..44f48264b83 100644 --- a/Sources/Sentry/include/HybridPublic/PrivateSentrySDKOnly.h +++ b/Sources/Sentry/include/HybridPublic/PrivateSentrySDKOnly.h @@ -198,7 +198,6 @@ typedef void (^SentryOnAppStartMeasurementAvailable)( + (void)addReplayRedactClasses:(NSArray *_Nonnull)classes; + (void)setIgnoreContainerClass:(Class _Nonnull)containerClass; + (void)setRedactContainerClass:(Class _Nonnull)containerClass; -+ (void)setReplaySdkInfo:(NSDictionary *)sdkInfo; #endif + (nullable NSDictionary *)appStartMeasurementWithSpans; diff --git a/Sources/Sentry/include/SentrySessionReplayIntegration+Private.h b/Sources/Sentry/include/SentrySessionReplayIntegration+Private.h index 1fe037a93ad..af8d6d5da19 100644 --- a/Sources/Sentry/include/SentrySessionReplayIntegration+Private.h +++ b/Sources/Sentry/include/SentrySessionReplayIntegration+Private.h @@ -16,8 +16,6 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, strong) SentryViewPhotographer *viewPhotographer; -@property (nonatomic, strong, nullable) NSDictionary *sdkInfo; - @end NS_ASSUME_NONNULL_END diff --git a/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift b/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift index 7e2a8e0029b..a007c1fc66a 100644 --- a/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift +++ b/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift @@ -1,4 +1,5 @@ import Foundation +@_implementationOnly import _SentryPrivate @objcMembers public class SentryReplayOptions: NSObject, SentryRedactOptions { @@ -146,6 +147,10 @@ public class SentryReplayOptions: NSObject, SentryRedactOptions { */ let maximumDuration = TimeInterval(3_600) + /** + * Used by hybrid SDKs to be able to configure SDK info for Session Replay + */ + var sdkInfo: [String: Any]? /** * Inittialize session replay options disabled */ @@ -183,5 +188,6 @@ public class SentryReplayOptions: NSObject, SentryRedactOptions { if let quality = SentryReplayQuality(rawValue: dictionary["quality"] as? Int ?? -1) { self.quality = quality } + sdkInfo = dictionary["sdkInfo"] as? [String: Any] } } From 68b262431b42db49f921062f0da7a3c07b3f6dc0 Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Tue, 24 Dec 2024 08:27:35 +0000 Subject: [PATCH 08/15] Format code --- Sources/Sentry/SentrySessionReplayIntegration.m | 8 ++++---- .../Integrations/SessionReplay/SentryReplayOptions.swift | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/Sentry/SentrySessionReplayIntegration.m b/Sources/Sentry/SentrySessionReplayIntegration.m index 20cf046da44..9d2be45be95 100644 --- a/Sources/Sentry/SentrySessionReplayIntegration.m +++ b/Sources/Sentry/SentrySessionReplayIntegration.m @@ -18,13 +18,13 @@ # import "SentryReachability.h" # import "SentrySDK+Private.h" # import "SentryScope+Private.h" +# import "SentrySdkInfo.h" # import "SentrySerialization.h" # import "SentrySessionReplaySyncC.h" # import "SentrySwift.h" # import "SentrySwizzle.h" # import "SentryUIApplication.h" # import -# import "SentrySdkInfo.h" NS_ASSUME_NONNULL_BEGIN @@ -91,7 +91,7 @@ - (void)setupWith:(SentryReplayOptions *)replayOptions enableTouchTracker:(BOOL) _viewPhotographer = [[SentryViewPhotographer alloc] initWithRedactOptions:replayOptions]; _rateLimits = SentryDependencyContainer.sharedInstance.rateLimits; _sdkInfo = replayOptions.sdkInfo; - + if (touchTracker) { _touchTracker = [[SentryTouchTracker alloc] initWithDateProvider:SentryDependencyContainer.sharedInstance.dateProvider @@ -584,9 +584,9 @@ - (void)sessionReplayNewSegmentWithReplayEvent:(SentryReplayEvent *)replayEvent [self stop]; return; } - + replayEvent.sdk = _sdkInfo; - + [SentrySDK.currentHub captureReplayEvent:replayEvent replayRecording:replayRecording video:videoUrl]; diff --git a/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift b/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift index a007c1fc66a..2a75f41fe1d 100644 --- a/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift +++ b/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift @@ -1,5 +1,5 @@ -import Foundation @_implementationOnly import _SentryPrivate +import Foundation @objcMembers public class SentryReplayOptions: NSObject, SentryRedactOptions { From 589b0b57eaeac577bfbde60a817b1503c510a8a9 Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Tue, 24 Dec 2024 09:29:48 +0100 Subject: [PATCH 09/15] Apply suggestions from code review --- Sources/Sentry/SentrySessionReplayIntegration.m | 1 - Sources/Sentry/include/SentryPrivate.h | 1 - .../Sentry/include/SentrySessionReplayIntegration+Private.h | 6 +----- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Sources/Sentry/SentrySessionReplayIntegration.m b/Sources/Sentry/SentrySessionReplayIntegration.m index 9d2be45be95..b1afdbc6b2b 100644 --- a/Sources/Sentry/SentrySessionReplayIntegration.m +++ b/Sources/Sentry/SentrySessionReplayIntegration.m @@ -18,7 +18,6 @@ # import "SentryReachability.h" # import "SentrySDK+Private.h" # import "SentryScope+Private.h" -# import "SentrySdkInfo.h" # import "SentrySerialization.h" # import "SentrySessionReplaySyncC.h" # import "SentrySwift.h" diff --git a/Sources/Sentry/include/SentryPrivate.h b/Sources/Sentry/include/SentryPrivate.h index c1415fe1481..27c7ad8d640 100644 --- a/Sources/Sentry/include/SentryPrivate.h +++ b/Sources/Sentry/include/SentryPrivate.h @@ -13,7 +13,6 @@ #import "SentryDisplayLinkWrapper.h" #import "SentryLevelHelper.h" #import "SentryLogC.h" -#import "SentryMeta.h" #import "SentryRandom.h" #import "SentrySdkInfo.h" #import "SentrySession.h" diff --git a/Sources/Sentry/include/SentrySessionReplayIntegration+Private.h b/Sources/Sentry/include/SentrySessionReplayIntegration+Private.h index af8d6d5da19..b9d45561020 100644 --- a/Sources/Sentry/include/SentrySessionReplayIntegration+Private.h +++ b/Sources/Sentry/include/SentrySessionReplayIntegration+Private.h @@ -4,20 +4,16 @@ #if SENTRY_TARGET_REPLAY_SUPPORTED -NS_ASSUME_NONNULL_BEGIN - @class SentrySessionReplay; @class SentryViewPhotographer; @interface SentrySessionReplayIntegration () -@property (nonatomic, strong, nullable) SentrySessionReplay *sessionReplay; +@property (nonatomic, strong) SentrySessionReplay *sessionReplay; @property (nonatomic, strong) SentryViewPhotographer *viewPhotographer; @end -NS_ASSUME_NONNULL_END - #endif From c87f10b7f3ac7311c14f2892a66bdf1ecb36f620 Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Tue, 24 Dec 2024 09:43:14 +0100 Subject: [PATCH 10/15] test --- .../Sentry/SentrySessionReplayIntegration.m | 4 ---- Sources/Sentry/include/SentryPrivate.h | 1 + .../SessionReplay/SentryReplayOptions.swift | 1 + .../SessionReplay/SentrySessionReplay.swift | 1 + .../SentrySessionReplayTests.swift | 19 +++++++++++++++++++ 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/Sources/Sentry/SentrySessionReplayIntegration.m b/Sources/Sentry/SentrySessionReplayIntegration.m index b1afdbc6b2b..92a2b7785de 100644 --- a/Sources/Sentry/SentrySessionReplayIntegration.m +++ b/Sources/Sentry/SentrySessionReplayIntegration.m @@ -50,7 +50,6 @@ @implementation SentrySessionReplayIntegration { id _rateLimits; id _currentScreenshotProvider; id _currentBreadcrumbConverter; - NSDictionary *_sdkInfo; // We need to use this variable to identify whether rate limiting was ever activated for session // replay in this session, instead of always looking for the rate status in `SentryRateLimits` // This is the easiest way to ensure segment 0 will always reach the server, because session @@ -89,7 +88,6 @@ - (void)setupWith:(SentryReplayOptions *)replayOptions enableTouchTracker:(BOOL) _replayOptions = replayOptions; _viewPhotographer = [[SentryViewPhotographer alloc] initWithRedactOptions:replayOptions]; _rateLimits = SentryDependencyContainer.sharedInstance.rateLimits; - _sdkInfo = replayOptions.sdkInfo; if (touchTracker) { _touchTracker = [[SentryTouchTracker alloc] @@ -584,8 +582,6 @@ - (void)sessionReplayNewSegmentWithReplayEvent:(SentryReplayEvent *)replayEvent return; } - replayEvent.sdk = _sdkInfo; - [SentrySDK.currentHub captureReplayEvent:replayEvent replayRecording:replayRecording video:videoUrl]; diff --git a/Sources/Sentry/include/SentryPrivate.h b/Sources/Sentry/include/SentryPrivate.h index 27c7ad8d640..c1415fe1481 100644 --- a/Sources/Sentry/include/SentryPrivate.h +++ b/Sources/Sentry/include/SentryPrivate.h @@ -13,6 +13,7 @@ #import "SentryDisplayLinkWrapper.h" #import "SentryLevelHelper.h" #import "SentryLogC.h" +#import "SentryMeta.h" #import "SentryRandom.h" #import "SentrySdkInfo.h" #import "SentrySession.h" diff --git a/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift b/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift index 2a75f41fe1d..c2636ca751b 100644 --- a/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift +++ b/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift @@ -151,6 +151,7 @@ public class SentryReplayOptions: NSObject, SentryRedactOptions { * Used by hybrid SDKs to be able to configure SDK info for Session Replay */ var sdkInfo: [String: Any]? + /** * Inittialize session replay options disabled */ diff --git a/Sources/Swift/Integrations/SessionReplay/SentrySessionReplay.swift b/Sources/Swift/Integrations/SessionReplay/SentrySessionReplay.swift index c26507ab314..bbc9d319dc0 100644 --- a/Sources/Swift/Integrations/SessionReplay/SentrySessionReplay.swift +++ b/Sources/Swift/Integrations/SessionReplay/SentrySessionReplay.swift @@ -248,6 +248,7 @@ class SentrySessionReplay: NSObject { private func captureSegment(segment: Int, video: SentryVideoInfo, replayId: SentryId, replayType: SentryReplayType) { let replayEvent = SentryReplayEvent(eventId: replayId, replayStartTimestamp: video.start, replayType: replayType, segmentId: segment) + replayEvent.sdk = self.replayOptions.sdkInfo replayEvent.timestamp = video.end replayEvent.urls = video.screens diff --git a/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayTests.swift b/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayTests.swift index e3910c22c6a..5d7dbcf0a67 100644 --- a/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayTests.swift +++ b/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayTests.swift @@ -253,6 +253,25 @@ class SentrySessionReplayTests: XCTestCase { XCTAssertFalse(fixture.displayLink.isRunning()) } + func testSdkInfoIsSet() throws { + let fixture = Fixture() + let options = SentryReplayOptions(sessionSampleRate: 1, onErrorSampleRate: 1) + options.sdkInfo = ["version": "6.0.1", "name": "sentry.test"] + + let sut = fixture.getSut(options: options) + sut.start(rootView: fixture.rootView, fullSession: true) + + fixture.dateProvider.advance(by: 1) + Dynamic(sut).newFrame(nil) + fixture.dateProvider.advance(by: 5) + Dynamic(sut).newFrame(nil) + + let event = try XCTUnwrap(fixture.lastReplayEvent) + + XCTAssertEqual(event.sdk?["version"] as? String, "6.0.1") + XCTAssertEqual(event.sdk?["name"] as? String, "sentry.test") + } + func testSaveScreenShotInBufferMode() { let fixture = Fixture() From f10c3bb2158034f27af436898a8889e02a11839d Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Thu, 2 Jan 2025 15:01:35 +0100 Subject: [PATCH 11/15] changelog --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 435e9436718..bce8f151f99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,6 @@ ## Unreleased -### Improvements - -- Add native SDK information in the replay option event (#4663) ### Features - Session replay GA (#4662) @@ -13,6 +10,9 @@ - Remove empty session replay tags (#4667) +### Improvements + +- Add native SDK information in the replay option event (#4663) ## 8.43.0-beta.1 From 0759c23f75aa555bb86e818fb65ee034da267b55 Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Mon, 13 Jan 2025 09:57:56 +0100 Subject: [PATCH 12/15] sdk at envelope header --- CHANGELOG.md | 7 ++++++- Sources/Sentry/SentryClient.m | 10 ++++++---- Sources/Sentry/SentryMeta.m | 6 ++++-- Tests/SentryTests/SentryClientTests.swift | 20 ++++++++++++++++++++ 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5e28ac6805..0d9463ab97d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Improvements + +- Add native SDK information in the replay option event (#4663) + ## 8.43.1-beta.0 ### Fixes @@ -32,7 +38,6 @@ ### Improvements -- Add native SDK information in the replay option event (#4663) - Improve compiler error message for missing Swift declarations due to APPLICATION_EXTENSION_API_ONLY (#4603) - Mask screenshots for errors (#4623) - Slightly speed up serializing scope (#4661) diff --git a/Sources/Sentry/SentryClient.m b/Sources/Sentry/SentryClient.m index 49ef2445781..38224ffdb08 100644 --- a/Sources/Sentry/SentryClient.m +++ b/Sources/Sentry/SentryClient.m @@ -553,10 +553,12 @@ - (void)captureReplayEvent:(SentryReplayEvent *)replayEvent return; } - SentryEnvelope *envelope = [[SentryEnvelope alloc] - initWithHeader:[[SentryEnvelopeHeader alloc] initWithId:replayEvent.eventId] - items:@[ videoEnvelopeItem ]]; - + // Hybrid SDKs may override the sdk info for a replay Event, + // the same SDK should be used for the envelope header. + SentrySdkInfo* sdkInfo = replayEvent.sdk ? [[SentrySdkInfo alloc] initWithDict:replayEvent.sdk] : [SentrySdkInfo global]; + SentryEnvelopeHeader* envelopeHeader = [[SentryEnvelopeHeader alloc] initWithId:replayEvent.eventId sdkInfo:sdkInfo traceContext:nil]; + + SentryEnvelope *envelope = [[SentryEnvelope alloc] initWithHeader:envelopeHeader items:@[ videoEnvelopeItem ]]; [self captureEnvelope:envelope]; } diff --git a/Sources/Sentry/SentryMeta.m b/Sources/Sentry/SentryMeta.m index 626fa0bd30b..e65ed409211 100644 --- a/Sources/Sentry/SentryMeta.m +++ b/Sources/Sentry/SentryMeta.m @@ -13,8 +13,10 @@ @implementation SentryMeta + (void)initialize { - versionString = sentryVersionString.copy; - sdkName = sentrySdkName.copy; + if (self == [SentryMeta class]) { + versionString = sentryVersionString.copy; + sdkName = sentrySdkName.copy; + } } + (NSString *)versionString diff --git a/Tests/SentryTests/SentryClientTests.swift b/Tests/SentryTests/SentryClientTests.swift index 7d1da2aea89..1e212f8a0fc 100644 --- a/Tests/SentryTests/SentryClientTests.swift +++ b/Tests/SentryTests/SentryClientTests.swift @@ -1953,6 +1953,26 @@ class SentryClientTest: XCTestCase { XCTAssertNil(replayEvent.debugMeta) } + func testCaptureReplayEvent_overrideEnvelopeHeaderSDKInfo() throws { + let sut = fixture.getSut() + let replayEvent = SentryReplayEvent(eventId: SentryId(), replayStartTimestamp: Date(), replayType: .session, segmentId: 2) + replayEvent.sdk = ["name": "Test SDK", "version": "1.0.0"] + let replayRecording = SentryReplayRecording(segmentId: 2, size: 200, start: Date(timeIntervalSince1970: 2), duration: 5_000, frameCount: 5, frameRate: 1, height: 930, width: 390, extraEvents: []) + + //Not a video url, but its ok for test the envelope + let movieUrl = try XCTUnwrap(Bundle(for: self.classForCoder).url(forResource: "Resources/raw", withExtension: "json")) + + let scope = Scope() + scope.addBreadcrumb(Breadcrumb(level: .debug, category: "Test Breadcrumb")) + + sut.capture(replayEvent, replayRecording: replayRecording, video: movieUrl, with: scope) + + let header = try XCTUnwrap(self.fixture.transport.sentEnvelopes.first?.header) + + XCTAssertEqual(header.sdkInfo?.name, "Test SDK") + XCTAssertEqual(header.sdkInfo?.version, "1.0.0") + } + func testCaptureCrashEventSetReplayInScope() { let sut = fixture.getSut() let event = Event() From 6789c9c6eb2767db74b2d17505cf1d3daaf83ced Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Mon, 13 Jan 2025 08:59:02 +0000 Subject: [PATCH 13/15] Format code --- Sources/Sentry/SentryClient.m | 13 +++++++++---- Sources/Sentry/SentryMeta.m | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Sources/Sentry/SentryClient.m b/Sources/Sentry/SentryClient.m index 38224ffdb08..07a21911394 100644 --- a/Sources/Sentry/SentryClient.m +++ b/Sources/Sentry/SentryClient.m @@ -555,10 +555,15 @@ - (void)captureReplayEvent:(SentryReplayEvent *)replayEvent // Hybrid SDKs may override the sdk info for a replay Event, // the same SDK should be used for the envelope header. - SentrySdkInfo* sdkInfo = replayEvent.sdk ? [[SentrySdkInfo alloc] initWithDict:replayEvent.sdk] : [SentrySdkInfo global]; - SentryEnvelopeHeader* envelopeHeader = [[SentryEnvelopeHeader alloc] initWithId:replayEvent.eventId sdkInfo:sdkInfo traceContext:nil]; - - SentryEnvelope *envelope = [[SentryEnvelope alloc] initWithHeader:envelopeHeader items:@[ videoEnvelopeItem ]]; + SentrySdkInfo *sdkInfo = replayEvent.sdk ? [[SentrySdkInfo alloc] initWithDict:replayEvent.sdk] + : [SentrySdkInfo global]; + SentryEnvelopeHeader *envelopeHeader = + [[SentryEnvelopeHeader alloc] initWithId:replayEvent.eventId + sdkInfo:sdkInfo + traceContext:nil]; + + SentryEnvelope *envelope = [[SentryEnvelope alloc] initWithHeader:envelopeHeader + items:@[ videoEnvelopeItem ]]; [self captureEnvelope:envelope]; } diff --git a/Sources/Sentry/SentryMeta.m b/Sources/Sentry/SentryMeta.m index e65ed409211..29b1181f150 100644 --- a/Sources/Sentry/SentryMeta.m +++ b/Sources/Sentry/SentryMeta.m @@ -13,7 +13,7 @@ @implementation SentryMeta + (void)initialize { - if (self == [SentryMeta class]) { + if (self == [SentryMeta class]) { versionString = sentryVersionString.copy; sdkName = sentrySdkName.copy; } From 824492b985098160217bc9cd7767af32a1f523ca Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Wed, 15 Jan 2025 11:45:18 +0100 Subject: [PATCH 14/15] rollback sentrymeta change --- Sources/Sentry/SentryMeta.m | 25 ++----------------- Sources/Sentry/include/SentryMeta.h | 15 ----------- .../RRWeb/SentryRRWebOptionsEvent.swift | 4 +-- 3 files changed, 4 insertions(+), 40 deletions(-) diff --git a/Sources/Sentry/SentryMeta.m b/Sources/Sentry/SentryMeta.m index 29b1181f150..2451d64cdcf 100644 --- a/Sources/Sentry/SentryMeta.m +++ b/Sources/Sentry/SentryMeta.m @@ -2,22 +2,11 @@ @implementation SentryMeta -const NSString *const sentryVersionString = @"8.43.1-beta.0"; -const NSString *const sentrySdkName = @"sentry.cocoa"; - // Don't remove the static keyword. If you do the compiler adds the constant name to the global // symbol table and it might clash with other constants. When keeping the static keyword the // compiler replaces all occurrences with the value. -static NSString *versionString; -static NSString *sdkName; - -+ (void)initialize -{ - if (self == [SentryMeta class]) { - versionString = sentryVersionString.copy; - sdkName = sentrySdkName.copy; - } -} +static NSString *versionString = @"8.43.1-beta.0"; +static NSString *sdkName = @"sentry.cocoa"; + (NSString *)versionString { @@ -39,14 +28,4 @@ + (void)setSdkName:(NSString *)value sdkName = value; } -+ (NSString *)nativeSdkName -{ - return sentrySdkName.copy; -} - -+ (NSString *)nativeVersionString -{ - return sentryVersionString.copy; -} - @end diff --git a/Sources/Sentry/include/SentryMeta.h b/Sources/Sentry/include/SentryMeta.h index 916ac62e4c0..3ee7fd9efc4 100644 --- a/Sources/Sentry/include/SentryMeta.h +++ b/Sources/Sentry/include/SentryMeta.h @@ -14,21 +14,6 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, class, copy) NSString *sdkName; -/** - * Return a version string e.g: 1.2.3 (3) - * This always report the version of Sentry.cocoa, - * `versionString` can be changed by hybrid SDKs. - * We can use this property to get which version of Sentry cocoa - * the hybrid SDK is using. - */ -@property (nonatomic, class, readonly) NSString *nativeVersionString; - -/** - * Returns "sentry.cocoa" - * `sdkName` can be changed by hybrid SDKs. - */ -@property (nonatomic, class, readonly) NSString *nativeSdkName; - @end NS_ASSUME_NONNULL_END diff --git a/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebOptionsEvent.swift b/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebOptionsEvent.swift index 5654b474ef3..fa7adb19991 100644 --- a/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebOptionsEvent.swift +++ b/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebOptionsEvent.swift @@ -10,8 +10,8 @@ import Foundation "maskAllText": options.maskAllText, "maskAllImages": options.maskAllImages, "quality": String(describing: options.quality), - "nativeSdkName": SentryMeta.nativeSdkName, - "nativeSdkVersion": SentryMeta.nativeVersionString + "nativeSdkName": SentryMeta.sdkName, + "nativeSdkVersion": SentryMeta.versionString ] if !options.maskedViewClasses.isEmpty { From cc95c89c9121cc36495217790dec9a5c12628454 Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Wed, 15 Jan 2025 11:45:47 +0100 Subject: [PATCH 15/15] Update SentrySessionReplayTests.swift --- .../Integrations/SessionReplay/SentrySessionReplayTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayTests.swift b/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayTests.swift index aec1be045ce..747a0b3a479 100644 --- a/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayTests.swift +++ b/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayTests.swift @@ -447,8 +447,8 @@ class SentrySessionReplayTests: XCTestCase { XCTAssertNil(options["maskedViewClasses"]) XCTAssertNil(options["unmaskedViewClasses"]) XCTAssertEqual(options["quality"] as? String, "medium") - XCTAssertEqual(options["nativeSdkName"] as? String, SentryMeta.nativeSdkName) - XCTAssertEqual(options["nativeSdkVersion"] as? String, SentryMeta.nativeVersionString) + XCTAssertEqual(options["nativeSdkName"] as? String, SentryMeta.sdkName) + XCTAssertEqual(options["nativeSdkVersion"] as? String, SentryMeta.versionString) } func testOptionsInTheEventAllChanged() throws {