diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e0f5af0db..8b3ddf794b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ via the option `swizzleClassNameExclude`. - Finish TTID correctly when viewWillAppear is skipped (#4417) - Swizzling RootUIViewController if ignored by `swizzleClassNameExclude` (#4407) - Data race in SentrySwizzleInfo.originalCalled (#4434) +- Thread running at user-initiated quality-of-service for session replay (#4439) ### Improvements diff --git a/Sources/Sentry/SentrySessionReplayIntegration.m b/Sources/Sentry/SentrySessionReplayIntegration.m index e2db6fc3c8..3ecd0e1972 100644 --- a/Sources/Sentry/SentrySessionReplayIntegration.m +++ b/Sources/Sentry/SentrySessionReplayIntegration.m @@ -281,6 +281,12 @@ - (void)startWithOptions:(SentryReplayOptions *)replayOptions = (NSInteger)(shouldReplayFullSession ? replayOptions.sessionSegmentDuration + 1 : replayOptions.errorReplayDuration + 1); + dispatch_queue_attr_t attributes = dispatch_queue_attr_make_with_qos_class( + DISPATCH_QUEUE_SERIAL, DISPATCH_QUEUE_PRIORITY_LOW, 0); + SentryDispatchQueueWrapper *dispatchQueue = + [[SentryDispatchQueueWrapper alloc] initWithName:"io.sentry.session-replay" + attributes:attributes]; + self.sessionReplay = [[SentrySessionReplay alloc] initWithReplayOptions:replayOptions replayFolderPath:docs @@ -290,7 +296,7 @@ - (void)startWithOptions:(SentryReplayOptions *)replayOptions touchTracker:_touchTracker dateProvider:SentryDependencyContainer.sharedInstance.dateProvider delegate:self - dispatchQueue:[[SentryDispatchQueueWrapper alloc] init] + dispatchQueue:dispatchQueue displayLinkWrapper:[[SentryDisplayLinkWrapper alloc] init]]; [self.sessionReplay diff --git a/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayTests.swift b/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayTests.swift index b9b3e02e98..d2622b661a 100644 --- a/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayTests.swift +++ b/Tests/SentryTests/Integrations/SessionReplay/SentrySessionReplayTests.swift @@ -17,6 +17,8 @@ class SentrySessionReplayTests: XCTestCase { private class TestReplayMaker: NSObject, SentryReplayVideoMaker { var screens = [String]() + var createVideoCallBack: ((SentryVideoInfo) -> Void)? + struct CreateVideoCall { var beginning: Date var end: Date @@ -30,6 +32,7 @@ class SentrySessionReplayTests: XCTestCase { try? "Video Data".write(to: outputFileURL, atomically: true, encoding: .utf8) let videoInfo = SentryVideoInfo(path: outputFileURL, height: 1_024, width: 480, duration: end.timeIntervalSince(beginning), frameCount: 5, frameRate: 1, start: beginning, end: end, fileSize: 10, screens: screens) + createVideoCallBack?(videoInfo) return [videoInfo] } @@ -63,7 +66,7 @@ class SentrySessionReplayTests: XCTestCase { var lastReplayId: SentryId? var currentScreen: String? - func getSut(options: SentryReplayOptions = .init(sessionSampleRate: 0, onErrorSampleRate: 0) ) -> SentrySessionReplay { + func getSut(options: SentryReplayOptions = .init(sessionSampleRate: 0, onErrorSampleRate: 0), dispatchQueue: SentryDispatchQueueWrapper = TestSentryDispatchQueueWrapper() ) -> SentrySessionReplay { return SentrySessionReplay(replayOptions: options, replayFolderPath: cacheFolder, screenshotProvider: screenshotProvider, @@ -72,7 +75,7 @@ class SentrySessionReplayTests: XCTestCase { touchTracker: SentryTouchTracker(dateProvider: dateProvider, scale: 0), dateProvider: dateProvider, delegate: self, - dispatchQueue: TestSentryDispatchQueueWrapper(), + dispatchQueue: dispatchQueue, displayLinkWrapper: displayLink) } @@ -147,7 +150,7 @@ class SentrySessionReplayTests: XCTestCase { XCTAssertNotNil(fixture.lastReplayRecording) assertFullSession(sut, expected: true) } - + func testReplayScreenNames() throws { let fixture = Fixture() let sut = fixture.getSut(options: SentryReplayOptions(sessionSampleRate: 1, onErrorSampleRate: 1))