Skip to content

Commit

Permalink
feat: Session Replay GA (#4662)
Browse files Browse the repository at this point in the history
Remove SR from being experimental and make it GA.

Co-authored-by: Sentry Github Bot <[email protected]>
  • Loading branch information
brustolin and getsentry-bot authored Jan 2, 2025
1 parent e9dfabe commit 0aea1a1
Show file tree
Hide file tree
Showing 11 changed files with 55 additions and 47 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

### Features

- Session replay GA (#4662)

## 8.43.0-beta.1

### Improvements
Expand Down
10 changes: 5 additions & 5 deletions Samples/iOS-ObjectiveC/iOS-ObjectiveC/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -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:@""];
Expand Down
4 changes: 2 additions & 2 deletions Samples/iOS-Swift/iOS-Swift/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion Samples/iOS-SwiftUI/iOS-SwiftUI/SwiftUIApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions Sources/Sentry/Public/SentryOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
@class SentryMeasurementValue;
@class SentryReplayOptions;
@class SentryScope;
@class SentryReplayOptions;

NS_SWIFT_NAME(Options)
@interface SentryOptions : NSObject
Expand Down Expand Up @@ -370,6 +371,15 @@ NS_SWIFT_NAME(Options)

#endif // SENTRY_UIKIT_AVAILABLE

#if SENTRY_TARGET_REPLAY_SUPPORTED

/**
* Settings to configure the session replay.
*/
@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.
Expand Down
15 changes: 5 additions & 10 deletions Sources/Sentry/SentryBaseIntegration.m
Original file line number Diff line number Diff line change
Expand Up @@ -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.experimental.sessionReplay.onErrorSampleRate == 0
&& options.experimental.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"];
Expand Down
12 changes: 12 additions & 0 deletions Sources/Sentry/SentryOptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -468,6 +473,13 @@ - (BOOL)validateOptions:(NSDictionary<NSString *, id> *)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; }];

Expand Down
7 changes: 3 additions & 4 deletions Sources/Sentry/SentrySessionReplayIntegration.m
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,8 @@ - (instancetype)init
- (instancetype)initForManualUse:(nonnull SentryOptions *)options
{
if (self = [super init]) {
[self setupWith:options.experimental.sessionReplay
enableTouchTracker:options.enableSwizzling];
[self startWithOptions:options.experimental.sessionReplay fullSession:YES];
[self setupWith:options.sessionReplay enableTouchTracker:options.enableSwizzling];
[self startWithOptions:options.sessionReplay fullSession:YES];
}
return self;
}
Expand All @@ -79,7 +78,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;
}

Expand Down
13 changes: 0 additions & 13 deletions Sources/Swift/SentryExperimentalOptions.swift
Original file line number Diff line number Diff line change
@@ -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
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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://[email protected]/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
Expand Down Expand Up @@ -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()
Expand All @@ -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()
Expand Down
17 changes: 8 additions & 9 deletions Tests/SentryTests/SentryOptionsTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -887,20 +887,19 @@ - (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.experimental.sessionReplay.sessionSampleRate, 2);
XCTAssertEqual(options.experimental.sessionReplay.onErrorSampleRate, 4);
XCTAssertEqual(options.sessionReplay.sessionSampleRate, 2);
XCTAssertEqual(options.sessionReplay.onErrorSampleRate, 4);
}
}

- (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);
}
}

Expand Down

0 comments on commit 0aea1a1

Please sign in to comment.