diff --git a/CHANGELOG.md b/CHANGELOG.md index d14bfa61374..6d48dd7e4d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ for SIGTERM reporting in the last release and enabled it by default. For some users, SIGTERM events were verbose and not actionable. Therefore, we disable it per default in this release. If you'd like to receive SIGTERM events, set the option `enableSigtermReporting = true`. +- Add replay quality option (#4035) ### Improvements diff --git a/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift b/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift index b1e43b65198..dd0d729d0d3 100644 --- a/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift +++ b/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift @@ -30,6 +30,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { if #available(iOS 16.0, *) { options.experimental.sessionReplay = SentryReplayOptions(sessionSampleRate: 1, errorSampleRate: 1, redactAllText: true, redactAllImages: true) + options.experimental.sessionReplay.quality = .high } if #available(iOS 15.0, *) { diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index 451bbe557b3..86f23e66517 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -914,6 +914,7 @@ D8CB742E294B294B00A5F964 /* MockUIScene.m in Sources */ = {isa = PBXBuildFile; fileRef = D8CB742D294B294B00A5F964 /* MockUIScene.m */; }; D8CCFC632A1520C900DE232E /* SentryBinaryImageCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D8CCFC622A1520C900DE232E /* SentryBinaryImageCacheTests.m */; }; D8CE69BC277E39C700C6EC5C /* SentryFileIOTrackingIntegrationObjCTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D8CE69BB277E39C700C6EC5C /* SentryFileIOTrackingIntegrationObjCTests.m */; }; + D8DBE0D22C0EFFC300FAB1FD /* SentryReplayOptionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8DBE0D12C0EFFC300FAB1FD /* SentryReplayOptionsTests.swift */; }; D8F016B32B9622D6007B9AFB /* SentryId.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F016B22B9622D6007B9AFB /* SentryId.swift */; }; D8F016B62B962548007B9AFB /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F016B52B962548007B9AFB /* StringExtensions.swift */; }; D8F67AEE2BE0D19200C9197B /* UIImageHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F67AED2BE0D19200C9197B /* UIImageHelper.swift */; }; @@ -1981,6 +1982,7 @@ D8CB742D294B294B00A5F964 /* MockUIScene.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockUIScene.m; sourceTree = ""; }; D8CCFC622A1520C900DE232E /* SentryBinaryImageCacheTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryBinaryImageCacheTests.m; sourceTree = ""; }; D8CE69BB277E39C700C6EC5C /* SentryFileIOTrackingIntegrationObjCTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryFileIOTrackingIntegrationObjCTests.m; sourceTree = ""; }; + D8DBE0D12C0EFFC300FAB1FD /* SentryReplayOptionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryReplayOptionsTests.swift; sourceTree = ""; }; D8F016B22B9622D6007B9AFB /* SentryId.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryId.swift; sourceTree = ""; }; D8F016B52B962548007B9AFB /* StringExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtensions.swift; sourceTree = ""; }; D8F01DE42A126B62008F4996 /* HybridPod.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; path = HybridPod.podspec; sourceTree = ""; }; @@ -3605,6 +3607,7 @@ D861301B2BB5A267004C0F5E /* SentrySessionReplayTests.swift */, D8AFC0002BD252B900118BE1 /* SentryOnDemandReplayTests.swift */, D82DD1CC2BEEB1A0001AB556 /* SentryBreadcrumbReplayConverterTests.swift */, + D8DBE0D12C0EFFC300FAB1FD /* SentryReplayOptionsTests.swift */, ); path = SessionReplay; sourceTree = ""; @@ -4949,6 +4952,7 @@ 7BD86ECD264A78A6005439DB /* SentryAppStartTrackerTests.swift in Sources */, 7BB6550D253EEB3900887E87 /* SentryUserFeedbackTests.swift in Sources */, 7BBD18B7245180FF00427C76 /* SentryDsnTests.m in Sources */, + D8DBE0D22C0EFFC300FAB1FD /* SentryReplayOptionsTests.swift in Sources */, 62950F1029E7FE0100A42624 /* SentryTransactionContextTests.swift in Sources */, 0A2D7BBA29152CBF008727AF /* SentryWatchdogTerminationsScopeObserverTests.swift in Sources */, 7BD4BD4B27EB2DC20071F4FF /* SentryDiscardedEventTests.swift in Sources */, diff --git a/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift b/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift index ce0f3fcfb32..1ef0b53f35e 100644 --- a/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift +++ b/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift @@ -2,6 +2,30 @@ import Foundation @objcMembers public class SentryReplayOptions: NSObject, SentryRedactOptions { + + /** + * Enum to define the quality of the session replay. + */ + public enum SentryReplayQuality: Int { + /** + * Video Scale: 80% + * Bit Rate: 20.000 + */ + case low + + /** + * Video Scale: 100% + * Bit Rate: 40.000 + */ + case medium + + /** + * Video Scale: 100% + * Bit Rate: 60.000 + */ + case high + } + /** * Indicates the percentage in which the replay for the session will be created. * - Specifying @c 0 means never, @c 1.0 means always. @@ -37,23 +61,32 @@ public class SentryReplayOptions: NSObject, SentryRedactOptions { public var redactAllImages = true /** - * Defines the quality of the session replay. - * Higher bit rates better quality, but also bigger files to transfer. - * @note The default value is @c 20000; + * Indicates the quality of the replay. + * The higher the quality, the higher the CPU and bandwidth usage. */ - let replayBitRate = 20_000 + public var quality = SentryReplayQuality.low /** - * Number of frames per second of the replay. - * The more the havier the process is. + * Defines the quality of the session replay. + * Higher bit rates better quality, but also bigger files to transfer. */ - let frameRate = 1 + var replayBitRate: Int { + quality.rawValue * 20_000 + 20_000 + } /** * The scale related to the window size at which the replay will be created */ - let sizeScale = 0.8 + var sizeScale: Float { + quality == .low ? 0.8 : 1.0 + } + /** + * Number of frames per second of the replay. + * The more the havier the process is. + */ + let frameRate = 1 + /** * The maximum duration of replays for error events. */ diff --git a/Tests/SentryTests/Integrations/SessionReplay/SentryReplayOptionsTests.swift b/Tests/SentryTests/Integrations/SessionReplay/SentryReplayOptionsTests.swift new file mode 100644 index 00000000000..6dcc51fb987 --- /dev/null +++ b/Tests/SentryTests/Integrations/SessionReplay/SentryReplayOptionsTests.swift @@ -0,0 +1,31 @@ +import Foundation +@testable import Sentry +import XCTest + +class SentryReplayOptionsTests: XCTestCase { + + func testQualityLow() { + let options = SentryReplayOptions() + + XCTAssertEqual(options.quality, .low) + XCTAssertEqual(options.replayBitRate, 20_000) + XCTAssertEqual(options.sizeScale, 0.8) + } + + func testQualityMedium() { + let options = SentryReplayOptions() + options.quality = .medium + + XCTAssertEqual(options.replayBitRate, 40_000) + XCTAssertEqual(options.sizeScale, 1.0) + } + + func testQualityHigh() { + let options = SentryReplayOptions() + options.quality = .high + + XCTAssertEqual(options.replayBitRate, 60_000) + XCTAssertEqual(options.sizeScale, 1.0) + } + +}