Skip to content

Commit

Permalink
Chore: Persist SR Screenshot provider and breadcrumbs converter (#4656)
Browse files Browse the repository at this point in the history
This is a fix for hybrid SDK, where the screenshot provider and the breadcrumb converter was reverting to the default after starting a new app session, usually when the app stays too long in the background.
  • Loading branch information
brustolin authored Dec 20, 2024
1 parent 0cb72fd commit 07c92b3
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 7 deletions.
9 changes: 7 additions & 2 deletions Sources/Sentry/SentrySessionReplayIntegration.m
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ @implementation SentrySessionReplayIntegration {
SentryNSNotificationCenterWrapper *_notificationCenter;
SentryOnDemandReplay *_resumeReplayMaker;
id<SentryRateLimits> _rateLimits;
id<SentryViewScreenshotProvider> _currentScreenshotProvider;
id<SentryReplayBreadcrumbConverter> _currentBreadcrumbConverter;
// 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
Expand Down Expand Up @@ -269,8 +271,9 @@ - (void)startWithOptions:(SentryReplayOptions *)replayOptions
fullSession:(BOOL)shouldReplayFullSession
{
[self startWithOptions:replayOptions
screenshotProvider:_viewPhotographer
breadcrumbConverter:[[SentrySRDefaultBreadcrumbConverter alloc] init]
screenshotProvider:_currentScreenshotProvider ?: _viewPhotographer
breadcrumbConverter:_currentBreadcrumbConverter
?: [[SentrySRDefaultBreadcrumbConverter alloc] init]
fullSession:shouldReplayFullSession];
}

Expand Down Expand Up @@ -474,10 +477,12 @@ - (void)configureReplayWith:(nullable id<SentryReplayBreadcrumbConverter>)breadc
screenshotProvider:(nullable id<SentryViewScreenshotProvider>)screenshotProvider
{
if (breadcrumbConverter) {
_currentBreadcrumbConverter = breadcrumbConverter;
self.sessionReplay.breadcrumbConverter = breadcrumbConverter;
}

if (screenshotProvider) {
_currentScreenshotProvider = screenshotProvider;
self.sessionReplay.screenshotProvider = screenshotProvider;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@ NS_ASSUME_NONNULL_BEGIN

@interface SentrySessionReplayIntegration ()

- (void)startWithOptions:(SentryReplayOptions *)replayOptions
screenshotProvider:(id<SentryViewScreenshotProvider>)screenshotProvider
breadcrumbConverter:(id<SentryReplayBreadcrumbConverter>)breadcrumbConverter
fullSession:(BOOL)shouldReplayFullSession;

+ (id<SentryRRWebEvent>)createBreadcrumbwithTimestamp:(NSDate *)timestamp
category:(NSString *)category
message:(nullable NSString *)message
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,34 @@ class SentrySessionReplayIntegrationTests: XCTestCase {
XCTAssertEqual(dispatchQueue.dispatchAsyncCalled, 0)
}

func testPersistScreenshotProviderAndBreadcrumbConverter() throws {
class CustomImageProvider: NSObject, SentryViewScreenshotProvider {
func image(view: UIView, onComplete: @escaping Sentry.ScreenshotCallback) {
onComplete(UIImage())
}
}

class CustomBreadcrumbConverter: NSObject, SentryReplayBreadcrumbConverter {
func convert(from breadcrumb: Breadcrumb) -> (any Sentry.SentryRRWebEventProtocol)? {
return nil
}
}

startSDK(sessionSampleRate: 1, errorSampleRate: 0)
PrivateSentrySDKOnly.configureSessionReplay(with: CustomBreadcrumbConverter(),
screenshotProvider: CustomImageProvider())
let sut = try getSut()

XCTAssertTrue(sut.sessionReplay?.screenshotProvider is CustomImageProvider)
XCTAssertTrue(sut.sessionReplay?.breadcrumbConverter is CustomBreadcrumbConverter)

sut.stop()
sut.start()

XCTAssertTrue(sut.sessionReplay?.screenshotProvider is CustomImageProvider)
XCTAssertTrue(sut.sessionReplay?.breadcrumbConverter is CustomBreadcrumbConverter)
}

func createLastSessionReplay(writeSessionInfo: Bool = true, errorSampleRate: Double = 1) throws {
let replayFolder = replayFolder()
let jsonPath = replayFolder + "/replay.current"
Expand Down

0 comments on commit 07c92b3

Please sign in to comment.