From f986075d4ee9f951c0e9f0332a5f2851a61d628f Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Mon, 23 Dec 2024 10:32:14 +0100 Subject: [PATCH 1/7] SR GA --- CHANGELOG.md | 1 + .../iOS-ObjectiveC/iOS-ObjectiveC/AppDelegate.m | 10 +++++----- Samples/iOS-Swift/iOS-Swift/AppDelegate.swift | 4 ++-- Samples/iOS-SwiftUI/iOS-SwiftUI/SwiftUIApp.swift | 2 +- Sources/Sentry/Public/SentryOptions.h | 7 +++++++ Sources/Sentry/SentryBaseIntegration.m | 4 ++-- Sources/Sentry/SentryOptions.m | 11 +++++++++++ Sources/Sentry/SentrySessionReplayIntegration.m | 6 +++--- Sources/Swift/SentryExperimentalOptions.swift | 13 ------------- .../SentrySessionReplayIntegrationTests.swift | 6 +++--- Tests/SentryTests/SentryOptionsTest.m | 14 +++++++------- 11 files changed, 42 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3aef31fded3..7155806bff8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Features +- Session replay GA () - Show session replay options as replay tags (#4639) ### Fixes diff --git a/Samples/iOS-ObjectiveC/iOS-ObjectiveC/AppDelegate.m b/Samples/iOS-ObjectiveC/iOS-ObjectiveC/AppDelegate.m index add7e76bfb4..3aa4ecc8023 100644 --- a/Samples/iOS-ObjectiveC/iOS-ObjectiveC/AppDelegate.m +++ b/Samples/iOS-ObjectiveC/iOS-ObjectiveC/AppDelegate.m @@ -28,11 +28,11 @@ - (BOOL)application:(UIApplication *)application [[SentryHttpStatusCodeRange alloc] initWithMin:400 max:599]; options.failedRequestStatusCodes = @[ httpStatusCodeRange ]; - options.experimental.sessionReplay.quality = SentryReplayQualityMedium; - options.experimental.sessionReplay.maskAllText = true; - options.experimental.sessionReplay.maskAllImages = true; - options.experimental.sessionReplay.sessionSampleRate = 0; - options.experimental.sessionReplay.onErrorSampleRate = 1; + options.sessionReplay.quality = SentryReplayQualityMedium; + options.sessionReplay.maskAllText = true; + options.sessionReplay.maskAllImages = true; + options.sessionReplay.sessionSampleRate = 0; + options.sessionReplay.onErrorSampleRate = 1; options.initialScope = ^(SentryScope *scope) { [scope setTagValue:@"" forKey:@""]; diff --git a/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift b/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift index a793fa156d7..415f8f17f73 100644 --- a/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift +++ b/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift @@ -76,8 +76,8 @@ extension AppDelegate { options.debug = true if #available(iOS 16.0, *), enableSessionReplay { - options.experimental.sessionReplay = SentryReplayOptions(sessionSampleRate: 0, onErrorSampleRate: 1, maskAllText: true, maskAllImages: true) - options.experimental.sessionReplay.quality = .high + options.sessionReplay = SentryReplayOptions(sessionSampleRate: 0, onErrorSampleRate: 1, maskAllText: true, maskAllImages: true) + options.sessionReplay.quality = .high } if #available(iOS 15.0, *), enableMetricKit { diff --git a/Samples/iOS-SwiftUI/iOS-SwiftUI/SwiftUIApp.swift b/Samples/iOS-SwiftUI/iOS-SwiftUI/SwiftUIApp.swift index ee92d4a10c3..87dbe088b67 100644 --- a/Samples/iOS-SwiftUI/iOS-SwiftUI/SwiftUIApp.swift +++ b/Samples/iOS-SwiftUI/iOS-SwiftUI/SwiftUIApp.swift @@ -10,7 +10,7 @@ struct SwiftUIApp: App { options.debug = true options.tracesSampleRate = 1.0 options.profilesSampleRate = 1.0 - options.experimental.sessionReplay.sessionSampleRate = 1.0 + options.sessionReplay.sessionSampleRate = 1.0 options.initialScope = { scope in scope.injectGitInformation() return scope diff --git a/Sources/Sentry/Public/SentryOptions.h b/Sources/Sentry/Public/SentryOptions.h index 2f06444157f..5c1f577cfa2 100644 --- a/Sources/Sentry/Public/SentryOptions.h +++ b/Sources/Sentry/Public/SentryOptions.h @@ -14,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN @class SentryMeasurementValue; @class SentryReplayOptions; @class SentryScope; +@class SentryReplayOptions; NS_SWIFT_NAME(Options) @interface SentryOptions : NSObject @@ -370,6 +371,12 @@ NS_SWIFT_NAME(Options) #endif // SENTRY_UIKIT_AVAILABLE +#if SENTRY_TARGET_REPLAY_SUPPORTED + +@property (nonatomic, strong) SentryReplayOptions* sessionReplay; + +#endif // SENTRY_TARGET_REPLAY_SUPPORTED + /** * When enabled, the SDK tracks performance for HTTP requests if auto performance tracking and * @c enableSwizzling are enabled. diff --git a/Sources/Sentry/SentryBaseIntegration.m b/Sources/Sentry/SentryBaseIntegration.m index 35ea3988672..494060739c5 100644 --- a/Sources/Sentry/SentryBaseIntegration.m +++ b/Sources/Sentry/SentryBaseIntegration.m @@ -151,8 +151,8 @@ - (BOOL)shouldBeEnabledWithOptions:(SentryOptions *)options if (integrationOptions & kIntegrationOptionEnableReplay) { if (@available(iOS 16.0, tvOS 16.0, *)) { - if (options.experimental.sessionReplay.onErrorSampleRate == 0 - && options.experimental.sessionReplay.sessionSampleRate == 0) { + if (options.sessionReplay.onErrorSampleRate == 0 + && options.sessionReplay.sessionSampleRate == 0) { [self logWithOptionName:@"sessionReplaySettings"]; return NO; } diff --git a/Sources/Sentry/SentryOptions.m b/Sources/Sentry/SentryOptions.m index 9d9fc80085c..f510648ca76 100644 --- a/Sources/Sentry/SentryOptions.m +++ b/Sources/Sentry/SentryOptions.m @@ -139,6 +139,11 @@ - (instancetype)init self.enableAppHangTrackingV2 = NO; self.enableReportNonFullyBlockingAppHangs = YES; #endif // SENTRY_HAS_UIKIT + +#if SENTRY_TARGET_REPLAY_SUPPORTED + self.sessionReplay = [[SentryReplayOptions alloc] init]; +#endif + self.enableAppHangTracking = YES; self.appHangTimeoutInterval = 2.0; self.enableAutoBreadcrumbTracking = YES; @@ -468,6 +473,12 @@ - (BOOL)validateOptions:(NSDictionary *)options #endif // SENTRY_HAS_UIKIT +#if SENTRY_TARGET_REPLAY_SUPPORTED + if ([options[@"sessionReplay"] isKindOfClass:NSDictionary.class]) { + self.sessionReplay = [[SentryReplayOptions alloc] initWithDictionary:options[@"sessionReplay"]]; + } +#endif //SENTRY_TARGET_REPLAY_SUPPORTED + [self setBool:options[@"enableAppHangTracking"] block:^(BOOL value) { self->_enableAppHangTracking = value; }]; diff --git a/Sources/Sentry/SentrySessionReplayIntegration.m b/Sources/Sentry/SentrySessionReplayIntegration.m index 92a2b7785de..7f80c49b55f 100644 --- a/Sources/Sentry/SentrySessionReplayIntegration.m +++ b/Sources/Sentry/SentrySessionReplayIntegration.m @@ -66,9 +66,9 @@ - (instancetype)init - (instancetype)initForManualUse:(nonnull SentryOptions *)options { if (self = [super init]) { - [self setupWith:options.experimental.sessionReplay + [self setupWith:options.sessionReplay enableTouchTracker:options.enableSwizzling]; - [self startWithOptions:options.experimental.sessionReplay fullSession:YES]; + [self startWithOptions:options.sessionReplay fullSession:YES]; } return self; } @@ -79,7 +79,7 @@ - (BOOL)installWithOptions:(nonnull SentryOptions *)options return NO; } - [self setupWith:options.experimental.sessionReplay enableTouchTracker:options.enableSwizzling]; + [self setupWith:options.sessionReplay enableTouchTracker:options.enableSwizzling]; return YES; } diff --git a/Sources/Swift/SentryExperimentalOptions.swift b/Sources/Swift/SentryExperimentalOptions.swift index b8fbb23f254..19c914bedf0 100644 --- a/Sources/Swift/SentryExperimentalOptions.swift +++ b/Sources/Swift/SentryExperimentalOptions.swift @@ -1,18 +1,5 @@ @objcMembers public class SentryExperimentalOptions: NSObject { - #if canImport(UIKit) - /** - * Settings to configure the session replay. - */ - public var sessionReplay = SentryReplayOptions(sessionSampleRate: 0, onErrorSampleRate: 0) - #endif - func validateOptions(_ options: [String: Any]?) { - #if canImport(UIKit) - if let sessionReplayOptions = options?["sessionReplay"] as? [String: Any] { - sessionReplay = SentryReplayOptions(dictionary: sessionReplayOptions) - } - #endif } - } diff --git a/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayIntegrationTests.swift b/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayIntegrationTests.swift index cade64eb715..1d26d46cf3f 100644 --- a/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayIntegrationTests.swift @@ -46,7 +46,7 @@ class SentrySessionReplayIntegrationTests: XCTestCase { private func startSDK(sessionSampleRate: Float, errorSampleRate: Float, enableSwizzling: Bool = true, noIntegrations: Bool = false, configure: ((Options) -> Void)? = nil) { SentrySDK.start { $0.dsn = "https://user@test.com/test" - $0.experimental.sessionReplay = SentryReplayOptions(sessionSampleRate: sessionSampleRate, onErrorSampleRate: errorSampleRate) + $0.sessionReplay = SentryReplayOptions(sessionSampleRate: sessionSampleRate, onErrorSampleRate: errorSampleRate) $0.setIntegrations(noIntegrations ? [] : [SentrySessionReplayIntegration.self]) $0.enableSwizzling = enableSwizzling $0.cacheDirectoryPath = FileManager.default.temporaryDirectory.path @@ -288,7 +288,7 @@ class SentrySessionReplayIntegrationTests: XCTestCase { } startSDK(sessionSampleRate: 1, errorSampleRate: 1) { options in - options.experimental.sessionReplay.maskedViewClasses = [AnotherLabel.self] + options.sessionReplay.maskedViewClasses = [AnotherLabel.self] } let sut = try getSut() @@ -301,7 +301,7 @@ class SentrySessionReplayIntegrationTests: XCTestCase { } startSDK(sessionSampleRate: 1, errorSampleRate: 1) { options in - options.experimental.sessionReplay.unmaskedViewClasses = [AnotherLabel.self] + options.sessionReplay.unmaskedViewClasses = [AnotherLabel.self] } let sut = try getSut() diff --git a/Tests/SentryTests/SentryOptionsTest.m b/Tests/SentryTests/SentryOptionsTest.m index 5520ae55452..0a0f858a4f6 100644 --- a/Tests/SentryTests/SentryOptionsTest.m +++ b/Tests/SentryTests/SentryOptionsTest.m @@ -623,7 +623,7 @@ - (void)testNSNull_SetsDefaultValue #if SENTRY_HAS_UIKIT @"enableUIViewControllerTracing" : [NSNull null], @"attachScreenshot" : [NSNull null], - @"sessionReplayOptions" : [NSNull null], + @"sessionReplay" : [NSNull null], #endif // SENTRY_HAS_UIKIT @"enableAppHangTracking" : [NSNull null], @"appHangTimeoutInterval" : [NSNull null], @@ -689,8 +689,8 @@ - (void)assertDefaultValues:(SentryOptions *)options XCTAssertEqual(options.enablePreWarmedAppStartTracing, NO); XCTAssertEqual(options.attachViewHierarchy, NO); XCTAssertEqual(options.reportAccessibilityIdentifier, YES); - XCTAssertEqual(options.experimental.sessionReplay.onErrorSampleRate, 0); - XCTAssertEqual(options.experimental.sessionReplay.sessionSampleRate, 0); + XCTAssertEqual(options.sessionReplay.onErrorSampleRate, 0); + XCTAssertEqual(options.sessionReplay.sessionSampleRate, 0); #endif // SENTRY_HAS_UIKIT #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" @@ -890,8 +890,8 @@ - (void)testSessionReplaySettingsInit @"experimental" : @ { @"sessionReplay" : @ { @"sessionSampleRate" : @2, @"errorSampleRate" : @4 } } }]; - XCTAssertEqual(options.experimental.sessionReplay.sessionSampleRate, 2); - XCTAssertEqual(options.experimental.sessionReplay.onErrorSampleRate, 4); + XCTAssertEqual(options.sessionReplay.sessionSampleRate, 2); + XCTAssertEqual(options.sessionReplay.onErrorSampleRate, 4); } } @@ -899,8 +899,8 @@ - (void)testSessionReplaySettingsDefaults { if (@available(iOS 16.0, tvOS 16.0, *)) { SentryOptions *options = [self getValidOptions:@{ @"sessionReplayOptions" : @ {} }]; - XCTAssertEqual(options.experimental.sessionReplay.sessionSampleRate, 0); - XCTAssertEqual(options.experimental.sessionReplay.onErrorSampleRate, 0); + XCTAssertEqual(options.sessionReplay.sessionSampleRate, 0); + XCTAssertEqual(options.sessionReplay.onErrorSampleRate, 0); } } From 3796d44bf4e98413b1776078da91e71b20e5452d Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Mon, 23 Dec 2024 10:36:34 +0100 Subject: [PATCH 2/7] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7155806bff8..d5f054fd0fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ ### Features -- Session replay GA () +- Session replay GA (#4662) - Show session replay options as replay tags (#4639) ### Fixes From 2b9548f7d86bf14b75e453cf6138573f1373cd2b Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Mon, 23 Dec 2024 10:37:52 +0100 Subject: [PATCH 3/7] Update SentryOptions.h --- Sources/Sentry/Public/SentryOptions.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Sources/Sentry/Public/SentryOptions.h b/Sources/Sentry/Public/SentryOptions.h index 5c1f577cfa2..c5ed2a07b2d 100644 --- a/Sources/Sentry/Public/SentryOptions.h +++ b/Sources/Sentry/Public/SentryOptions.h @@ -373,6 +373,9 @@ NS_SWIFT_NAME(Options) #if SENTRY_TARGET_REPLAY_SUPPORTED +/** + * Settings to configure the session replay. + */ @property (nonatomic, strong) SentryReplayOptions* sessionReplay; #endif // SENTRY_TARGET_REPLAY_SUPPORTED From b22713d60f79f2203eaca916c772b1e38ae095a1 Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Mon, 23 Dec 2024 09:46:03 +0000 Subject: [PATCH 4/7] Format code --- Sources/Sentry/Public/SentryOptions.h | 2 +- Sources/Sentry/SentryOptions.m | 11 ++++++----- Sources/Sentry/SentrySessionReplayIntegration.m | 3 +-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Sources/Sentry/Public/SentryOptions.h b/Sources/Sentry/Public/SentryOptions.h index c5ed2a07b2d..d904f4bf471 100644 --- a/Sources/Sentry/Public/SentryOptions.h +++ b/Sources/Sentry/Public/SentryOptions.h @@ -376,7 +376,7 @@ NS_SWIFT_NAME(Options) /** * Settings to configure the session replay. */ -@property (nonatomic, strong) SentryReplayOptions* sessionReplay; +@property (nonatomic, strong) SentryReplayOptions *sessionReplay; #endif // SENTRY_TARGET_REPLAY_SUPPORTED diff --git a/Sources/Sentry/SentryOptions.m b/Sources/Sentry/SentryOptions.m index f510648ca76..fbb01307182 100644 --- a/Sources/Sentry/SentryOptions.m +++ b/Sources/Sentry/SentryOptions.m @@ -139,11 +139,11 @@ - (instancetype)init self.enableAppHangTrackingV2 = NO; self.enableReportNonFullyBlockingAppHangs = YES; #endif // SENTRY_HAS_UIKIT - + #if SENTRY_TARGET_REPLAY_SUPPORTED self.sessionReplay = [[SentryReplayOptions alloc] init]; #endif - + self.enableAppHangTracking = YES; self.appHangTimeoutInterval = 2.0; self.enableAutoBreadcrumbTracking = YES; @@ -475,10 +475,11 @@ - (BOOL)validateOptions:(NSDictionary *)options #if SENTRY_TARGET_REPLAY_SUPPORTED if ([options[@"sessionReplay"] isKindOfClass:NSDictionary.class]) { - self.sessionReplay = [[SentryReplayOptions alloc] initWithDictionary:options[@"sessionReplay"]]; + self.sessionReplay = + [[SentryReplayOptions alloc] initWithDictionary:options[@"sessionReplay"]]; } -#endif //SENTRY_TARGET_REPLAY_SUPPORTED - +#endif // SENTRY_TARGET_REPLAY_SUPPORTED + [self setBool:options[@"enableAppHangTracking"] block:^(BOOL value) { self->_enableAppHangTracking = value; }]; diff --git a/Sources/Sentry/SentrySessionReplayIntegration.m b/Sources/Sentry/SentrySessionReplayIntegration.m index 7f80c49b55f..d045eca7120 100644 --- a/Sources/Sentry/SentrySessionReplayIntegration.m +++ b/Sources/Sentry/SentrySessionReplayIntegration.m @@ -66,8 +66,7 @@ - (instancetype)init - (instancetype)initForManualUse:(nonnull SentryOptions *)options { if (self = [super init]) { - [self setupWith:options.sessionReplay - enableTouchTracker:options.enableSwizzling]; + [self setupWith:options.sessionReplay enableTouchTracker:options.enableSwizzling]; [self startWithOptions:options.sessionReplay fullSession:YES]; } return self; From 9ad51e43b301aa6fa4c6daee1be469e8ea4e216c Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Mon, 23 Dec 2024 10:57:53 +0100 Subject: [PATCH 5/7] Update SentryOptionsTest.m --- Tests/SentryTests/SentryOptionsTest.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Tests/SentryTests/SentryOptionsTest.m b/Tests/SentryTests/SentryOptionsTest.m index 0a0f858a4f6..e99f71be7fd 100644 --- a/Tests/SentryTests/SentryOptionsTest.m +++ b/Tests/SentryTests/SentryOptionsTest.m @@ -887,8 +887,7 @@ - (void)testSessionReplaySettingsInit { if (@available(iOS 16.0, tvOS 16.0, *)) { SentryOptions *options = [self getValidOptions:@{ - @"experimental" : - @ { @"sessionReplay" : @ { @"sessionSampleRate" : @2, @"errorSampleRate" : @4 } } + @"sessionReplay" : @ { @"sessionSampleRate" : @2, @"errorSampleRate" : @4 } }]; XCTAssertEqual(options.sessionReplay.sessionSampleRate, 2); XCTAssertEqual(options.sessionReplay.onErrorSampleRate, 4); From 6588600714af786bb9793505afb5696bea81a0f8 Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Mon, 23 Dec 2024 11:11:04 +0100 Subject: [PATCH 6/7] Update SentryBaseIntegration.m --- Sources/Sentry/SentryBaseIntegration.m | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/Sources/Sentry/SentryBaseIntegration.m b/Sources/Sentry/SentryBaseIntegration.m index 494060739c5..c66018cb42d 100644 --- a/Sources/Sentry/SentryBaseIntegration.m +++ b/Sources/Sentry/SentryBaseIntegration.m @@ -148,21 +148,16 @@ - (BOOL)shouldBeEnabledWithOptions:(SentryOptions *)options [self logWithOptionName:@"attachViewHierarchy"]; return NO; } - +#endif +#if SENTRY_TARGET_REPLAY_SUPPORTED if (integrationOptions & kIntegrationOptionEnableReplay) { - if (@available(iOS 16.0, tvOS 16.0, *)) { - if (options.sessionReplay.onErrorSampleRate == 0 - && options.sessionReplay.sessionSampleRate == 0) { - [self logWithOptionName:@"sessionReplaySettings"]; - return NO; - } - } else { - [self logWithReason:@"Session replay requires iOS 16 or above"]; + if (options.sessionReplay.onErrorSampleRate == 0 + && options.sessionReplay.sessionSampleRate == 0) { + [self logWithOptionName:@"sessionReplaySettings"]; return NO; } } #endif - if ((integrationOptions & kIntegrationOptionEnableCrashHandler) && !options.enableCrashHandler) { [self logWithOptionName:@"enableCrashHandler"]; From 1befb0b347e5ba05617f12ccdd3dd2042e5e0ce0 Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Mon, 23 Dec 2024 14:38:21 +0100 Subject: [PATCH 7/7] Update CHANGELOG.md --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b62d0372885..2ebac22becc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Features + +- Session replay GA (#4662) + ## 8.43.0-beta.1 ### Improvements @@ -10,7 +16,6 @@ ### Features -- Session replay GA (#4662) - Show session replay options as replay tags (#4639) ### Fixes