diff --git a/CHANGELOG.md b/CHANGELOG.md index 43b6c446ef..dd1c658b30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ ### Features - Make feature Metrics generally available, moving experimental options to top-level options (#7843) +- Add Session Replay network details capture, including request/response headers and bodies extraction (#7580, #7582, #7584, #7585, #7588, #7590, #7854) ### Fixes diff --git a/Sources/Sentry/SentryNetworkTracker.m b/Sources/Sentry/SentryNetworkTracker.m index 34bac932fc..fc5f47e28a 100644 --- a/Sources/Sentry/SentryNetworkTracker.m +++ b/Sources/Sentry/SentryNetworkTracker.m @@ -596,6 +596,10 @@ - (BOOL)isNetworkDetailCaptureEnabledFor:(NSString *)urlString options:(SentryOp return NO; } + if (!options.experimental.enableReplayNetworkDetailsCapturing) { + return NO; + } + if (!urlString) { return NO; } diff --git a/Sources/Swift/Helper/SentryEnabledFeaturesBuilder.swift b/Sources/Swift/Helper/SentryEnabledFeaturesBuilder.swift index 40792de7ff..f1a4a98a1a 100644 --- a/Sources/Swift/Helper/SentryEnabledFeaturesBuilder.swift +++ b/Sources/Swift/Helper/SentryEnabledFeaturesBuilder.swift @@ -46,6 +46,9 @@ import Foundation if options.experimental.enableUnhandledCPPExceptionsV2 { features.append("unhandledCPPExceptionsV2") } + if options.experimental.enableReplayNetworkDetailsCapturing { + features.append("replayNetworkDetails") + } if options.enableMetrics { features.append("metrics") } diff --git a/Sources/Swift/Integrations/Performance/Network/SentryNetworkTrackingIntegration.swift b/Sources/Swift/Integrations/Performance/Network/SentryNetworkTrackingIntegration.swift index c435bbb80b..4c8f892cad 100644 --- a/Sources/Swift/Integrations/Performance/Network/SentryNetworkTrackingIntegration.swift +++ b/Sources/Swift/Integrations/Performance/Network/SentryNetworkTrackingIntegration.swift @@ -43,7 +43,7 @@ final class SentryNetworkTrackingIntegration Breadcrumb { diff --git a/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift b/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift index 9a4c688f1a..9a222d3c65 100644 --- a/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift +++ b/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift @@ -498,7 +498,7 @@ class SentryNetworkTrackerTests: XCTestCase { XCTAssertEqual(payloadData["fragment"] as? String, "fragment") } -#if canImport(UIKit) && SENTRY_TARGET_REPLAY_SUPPORTED +#if os(iOS) || os(tvOS) /// Simple case - when network details are enabled, `addBreadcrumbForSessionTask` will include /// serialized network details in the breadcrumb data. func testAddBreadcrumb_withNetworkDetails_shouldIncludeSerializedDetailsInBreadcrumbData() throws { @@ -511,6 +511,7 @@ class SentryNetworkTrackerTests: XCTestCase { options.sessionReplay.networkDetailAllowUrls = ["api.example.com"] options.sessionReplay.networkResponseHeaders = ["Cache-Control"] options.sessionReplay.networkCaptureBodies = false + options.experimental.enableReplayNetworkDetailsCapturing = true let scope = Scope() let client = TestClient(options: options) diff --git a/Tests/SentryTests/Integrations/SessionReplay/SentryReplayOptionsObjcTests.m b/Tests/SentryTests/Integrations/SessionReplay/SentryReplayOptionsObjcTests.m index da6ac86fa1..c306b1c5cd 100644 --- a/Tests/SentryTests/Integrations/SessionReplay/SentryReplayOptionsObjcTests.m +++ b/Tests/SentryTests/Integrations/SessionReplay/SentryReplayOptionsObjcTests.m @@ -37,7 +37,6 @@ - (void)testInit_withoutArguments_shouldUseDefaults // Currently there is not Obj-C SDK support for network details // => assert it's turned off. - XCTAssertFalse(options.networkDetailHasUrls); } - (void)testInit_withAllArguments_shouldSetAllValues @@ -72,7 +71,6 @@ - (void)testInit_withAllArguments_shouldSetAllValues // Currently there is not Obj-C SDK support for network details // => assert it's turned off. - XCTAssertFalse(options.networkDetailHasUrls); } @end diff --git a/Tests/SentryTests/Integrations/SessionReplay/SentryReplayOptionsTests.swift b/Tests/SentryTests/Integrations/SessionReplay/SentryReplayOptionsTests.swift index 0538695727..2ded741c82 100644 --- a/Tests/SentryTests/Integrations/SessionReplay/SentryReplayOptionsTests.swift +++ b/Tests/SentryTests/Integrations/SessionReplay/SentryReplayOptionsTests.swift @@ -26,6 +26,7 @@ class SentryReplayOptionsTests: XCTestCase { XCTAssertEqual(options.sessionSegmentDuration, 5) XCTAssertEqual(options.maximumDuration, 60 * 60) + XCTAssertFalse(options.networkDetailHasUrls) XCTAssertEqual(options.networkDetailAllowUrls.count, 0) XCTAssertEqual(options.networkDetailDenyUrls.count, 0) XCTAssertTrue(options.networkCaptureBodies) @@ -69,6 +70,7 @@ class SentryReplayOptionsTests: XCTestCase { XCTAssertEqual(options.maximumDuration, 60 * 60) // Network details assertions + XCTAssertTrue(options.networkDetailHasUrls) XCTAssertEqual(options.networkDetailAllowUrls as? [String], ["https://api.example.com", "https://test.example.org"]) XCTAssertEqual(options.networkDetailDenyUrls as? [String], ["https://sensitive.example.com", "https://private.example.org"]) XCTAssertFalse(options.networkCaptureBodies) diff --git a/sdk_api.json b/sdk_api.json index fdb609af2d..035c31500a 100644 --- a/sdk_api.json +++ b/sdk_api.json @@ -36731,6 +36731,82 @@ "printedName": "init()", "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(im)init" }, + { + "accessors": [ + { + "accessorKind": "get", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declAttributes": [ + "Final", + "ObjC" + ], + "declKind": "Accessor", + "implicit": true, + "kind": "Accessor", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC35enableReplayNetworkDetailsCapturingSbvg", + "moduleName": "Sentry", + "name": "Get", + "printedName": "Get()", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(im)enableReplayNetworkDetailsCapturing" + }, + { + "accessorKind": "set", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ], + "declAttributes": [ + "Final", + "ObjC" + ], + "declKind": "Accessor", + "implicit": true, + "kind": "Accessor", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC35enableReplayNetworkDetailsCapturingSbvs", + "moduleName": "Sentry", + "name": "Set", + "printedName": "Set()", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(im)setEnableReplayNetworkDetailsCapturing:" + } + ], + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declAttributes": [ + "Final", + "HasStorage", + "ObjC" + ], + "declKind": "Var", + "hasStorage": true, + "kind": "Var", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC35enableReplayNetworkDetailsCapturingSbvp", + "moduleName": "Sentry", + "name": "enableReplayNetworkDetailsCapturing", + "printedName": "enableReplayNetworkDetailsCapturing", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(py)enableReplayNetworkDetailsCapturing" + }, { "accessors": [ { @@ -50338,49 +50414,6 @@ "printedName": "networkDetailDenyUrls", "usr": "s:6Sentry0A13ReplayOptionsC21networkDetailDenyUrlsSayAA0A12UrlMatchable_pGvp" }, - { - "accessors": [ - { - "accessorKind": "get", - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declAttributes": [ - "ObjC" - ], - "declKind": "Accessor", - "kind": "Accessor", - "mangledName": "$s6Sentry0A13ReplayOptionsC20networkDetailHasUrlsSbvg", - "moduleName": "Sentry", - "name": "Get", - "printedName": "Get()", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)networkDetailHasUrls" - } - ], - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declAttributes": [ - "ObjC" - ], - "declKind": "Var", - "kind": "Var", - "mangledName": "$s6Sentry0A13ReplayOptionsC20networkDetailHasUrlsSbvp", - "moduleName": "Sentry", - "name": "networkDetailHasUrls", - "printedName": "networkDetailHasUrls", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)networkDetailHasUrls" - }, { "accessors": [ {