Skip to content

Commit

Permalink
Merge 6364669 into 8411a0a
Browse files Browse the repository at this point in the history
  • Loading branch information
brustolin authored Sep 5, 2024
2 parents 8411a0a + 6364669 commit 852663f
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
### Fixes

- Resumes replay when the app becomes active (#4303)
- Session replay for crash not created because of a race condition (#4314)

## 8.36.0

Expand Down
36 changes: 31 additions & 5 deletions Sources/Sentry/SentrySessionReplayIntegration.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
NS_ASSUME_NONNULL_BEGIN

static NSString *SENTRY_REPLAY_FOLDER = @"replay";
static NSString *SENTRY_CURRENT_REPLAY = @"replay.current";
static NSString *SENTRY_LAST_REPLAY = @"replay.last";

/**
* We need to use this from the swizzled block
Expand Down Expand Up @@ -64,8 +66,8 @@ - (BOOL)installWithOptions:(nonnull SentryOptions *)options

_notificationCenter = SentryDependencyContainer.sharedInstance.notificationCenterWrapper;

[self moveCurrentReplay];
[SentrySDK.currentHub registerSessionListener:self];

[SentryGlobalEventProcessor.shared
addEventProcessor:^SentryEvent *_Nullable(SentryEvent *_Nonnull event) {
if (event.isCrashEvent) {
Expand All @@ -92,8 +94,9 @@ - (BOOL)installWithOptions:(nonnull SentryOptions *)options
- (void)resumePreviousSessionReplay:(SentryEvent *)event
{
NSURL *dir = [self replayDirectory];
NSData *lastReplay =
[NSData dataWithContentsOfURL:[dir URLByAppendingPathComponent:@"lastreplay"]];
NSURL *lastReplayUrl = [dir URLByAppendingPathComponent:SENTRY_LAST_REPLAY];
NSData *lastReplay = [NSData dataWithContentsOfURL:lastReplayUrl];

if (lastReplay == nil) {
return;
}
Expand Down Expand Up @@ -161,6 +164,10 @@ - (void)resumePreviousSessionReplay:(SentryEvent *)event
eventContext[@"replay"] =
[NSDictionary dictionaryWithObjectsAndKeys:replayId.sentryIdString, @"replay_id", nil];
event.context = eventContext;

if ([NSFileManager.defaultManager removeItemAtURL:lastReplayURL error:&error] == NO) {
SENTRY_LOG_ERROR(@"Can`t delete '%@': %@", SENTRY_LAST_REPLAY, error);
}
}

- (void)captureVideo:(SentryVideoInfo *)video
Expand Down Expand Up @@ -297,8 +304,8 @@ - (void)saveCurrentSessionInfo:(SentryId *)sessionId

NSData *data = [SentrySerialization dataWithJSONObject:info];

NSString *infoPath =
[[path stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"lastreplay"];
NSString *infoPath = [[path stringByDeletingLastPathComponent]
stringByAppendingPathComponent:SENTRY_CURRENT_REPLAY];
if ([NSFileManager.defaultManager fileExistsAtPath:infoPath]) {
[NSFileManager.defaultManager removeItemAtPath:infoPath error:nil];
}
Expand All @@ -308,6 +315,25 @@ - (void)saveCurrentSessionInfo:(SentryId *)sessionId
cStringUsingEncoding:NSUTF8StringEncoding]);
}

- (void)moveCurrentReplay
{
NSURL *path = [self replayDirectory];
NSURL *current = [path URLByAppendingPathComponent:SENTRY_CURRENT_REPLAY];
NSURL *last = [path URLByAppendingPathComponent:SENTRY_LAST_REPLAY];

NSError *error;
if ([NSFileManager.defaultManager fileExistsAtPath:last.path]) {
if ([NSFileManager.defaultManager removeItemAtURL:last error:&error] == NO) {
SENTRY_LOG_ERROR(@"Could not delete 'lastreplay' file: %@", error);
return;
}
}

if ([NSFileManager.defaultManager moveItemAtURL:current toURL:last error:nil] == NO) {
SENTRY_LOG_ERROR(@"Could not move 'currentreplay' to 'lastreplat': %@", error);
}
}

- (void)stop
{
[self.sessionReplay stop];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,7 @@ class SentrySessionReplayIntegrationTests: XCTestCase {

func testInstallFullSessionReplayButDontRunBecauseOfRandom() throws {
SentryDependencyContainer.sharedInstance().random = TestRandom(value: 0.3)

startSDK(sessionSampleRate: 0.2, errorSampleRate: 0)

XCTAssertEqual(SentrySDK.currentHub().trimmedInstalledIntegrationNames().count, 1)
XCTAssertEqual(SentryGlobalEventProcessor.shared().processors.count, 1)
let sut = try getSut()
Expand Down Expand Up @@ -198,6 +196,8 @@ class SentrySessionReplayIntegrationTests: XCTestCase {
}

func testSessionReplayForCrash() throws {
try createLastSessionReplay()

startSDK(sessionSampleRate: 1, errorSampleRate: 1)

let client = SentryClient(options: try XCTUnwrap(SentrySDK.options))
Expand All @@ -209,7 +209,6 @@ class SentrySessionReplayIntegrationTests: XCTestCase {
expectation.fulfill()
}

try createLastSessionReplay()
let crash = Event(error: NSError(domain: "Error", code: 1))
crash.context = [:]
crash.isCrashEvent = true
Expand All @@ -225,6 +224,8 @@ class SentrySessionReplayIntegrationTests: XCTestCase {
}

func testBufferReplayForCrash() throws {
try createLastSessionReplay(writeSessionInfo: false)

startSDK(sessionSampleRate: 1, errorSampleRate: 1)

let client = SentryClient(options: try XCTUnwrap(SentrySDK.options))
Expand All @@ -236,7 +237,6 @@ class SentrySessionReplayIntegrationTests: XCTestCase {
expectation.fulfill()
}

try createLastSessionReplay(writeSessionInfo: false)
let crash = Event(error: NSError(domain: "Error", code: 1))
crash.context = [:]
crash.isCrashEvent = true
Expand Down Expand Up @@ -308,13 +308,20 @@ class SentrySessionReplayIntegrationTests: XCTestCase {
}

func createLastSessionReplay(writeSessionInfo: Bool = true, errorSampleRate: Double = 1) throws {
let replayFolder = SentryDependencyContainer.sharedInstance().fileManager.sentryPath + "/replay"
let jsonPath = replayFolder + "/lastreplay"
let options = Options()
options.dsn = "https://user@test.com/test"
options.cacheDirectoryPath = FileManager.default.temporaryDirectory.path

let replayFolder = options.cacheDirectoryPath + "/io.sentry/\(options.parsedDsn?.getHash() ?? "")/replay"
let jsonPath = replayFolder + "/replay.current"
var sessionFolder = UUID().uuidString
let info: [String: Any] = ["replayId": SentryId().sentryIdString,
"path": sessionFolder,
"errorSampleRate": errorSampleRate]
let data = SentrySerialization.data(withJSONObject: info)

try FileManager.default.createDirectory(atPath: replayFolder, withIntermediateDirectories: true)

try data?.write(to: URL(fileURLWithPath: jsonPath))

sessionFolder = "\(replayFolder)/\(sessionFolder)"
Expand Down

0 comments on commit 852663f

Please sign in to comment.