feat(network-details): Extend SentryReplayOptions API with Session Replay Network Details configuration#7580
feat(network-details): Extend SentryReplayOptions API with Session Replay Network Details configuration#7580
Conversation
Semver Impact of This PR🟡 Minor (new features) 📋 Changelog PreviewThis is how your changes will appear in the changelog. This PR will not appear in the changelog. 🤖 This preview updates automatically when you update the PR. |
|
1d2a165 to
8e08354
Compare
Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift
Outdated
Show resolved
Hide resolved
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #7580 +/- ##
=============================================
- Coverage 86.173% 85.391% -0.783%
=============================================
Files 483 485 +2
Lines 28785 28859 +74
Branches 12504 12546 +42
=============================================
- Hits 24805 24643 -162
- Misses 3927 4170 +243
+ Partials 53 46 -7
... and 11 files with indirect coverage changes Continue to review full report in Codecov by Sentry.
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: URL pattern validation runs twice on dictionary init
- I removed pre-validation in the dictionary initializer and routed raw values to the private initializer so URL patterns are validated exactly once in a single source of truth.
Or push these changes by commenting:
@cursor push 95c595cf60
Preview (95c595cf60)
diff --git a/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift b/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift
--- a/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift
+++ b/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift
@@ -601,8 +601,8 @@
maximumDuration: (dictionary["maximumDuration"] as? NSNumber)?.doubleValue,
excludedViewClasses: (dictionary["excludedViewClasses"] as? [String]).map { Set($0) },
includedViewClasses: (dictionary["includedViewClasses"] as? [String]).map { Set($0) },
- networkDetailAllowUrls: Self.validateNetworkDetailUrlPatterns(from: dictionary["networkDetailAllowUrls"]),
- networkDetailDenyUrls: Self.validateNetworkDetailUrlPatterns(from: dictionary["networkDetailDenyUrls"]),
+ networkDetailAllowUrls: dictionary["networkDetailAllowUrls"],
+ networkDetailDenyUrls: dictionary["networkDetailDenyUrls"],
networkCaptureBodies: (dictionary["networkCaptureBodies"] as? NSNumber)?.boolValue,
networkRequestHeaders: Self.parseStringArray(from: dictionary["networkRequestHeaders"]),
networkResponseHeaders: Self.parseStringArray(from: dictionary["networkResponseHeaders"])
@@ -745,8 +745,8 @@
maximumDuration: TimeInterval?,
excludedViewClasses: Set<String>? = nil,
includedViewClasses: Set<String>? = nil,
- networkDetailAllowUrls: [Any]? = nil,
- networkDetailDenyUrls: [Any]? = nil,
+ networkDetailAllowUrls: Any? = nil,
+ networkDetailDenyUrls: Any? = nil,
networkCaptureBodies: Bool? = nil,
networkRequestHeaders: [String]? = nil,
networkResponseHeaders: [String]? = nil
Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift
Outdated
Show resolved
Hide resolved
Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift
Outdated
Show resolved
Hide resolved
Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift
Outdated
Show resolved
Hide resolved
Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift
Outdated
Show resolved
Hide resolved
Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift
Outdated
Show resolved
Hide resolved
Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift
Outdated
Show resolved
Hide resolved
Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift
Outdated
Show resolved
Hide resolved
Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift
Outdated
Show resolved
Hide resolved
Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 39fbc4b | 1230.95 ms | 1257.53 ms | 26.58 ms |
| 4c93fb8 | 1218.40 ms | 1249.93 ms | 31.53 ms |
| 99e74a3 | 1203.33 ms | 1248.57 ms | 45.24 ms |
| d52e416 | 1209.02 ms | 1239.56 ms | 30.53 ms |
| 16b3235 | 1234.51 ms | 1257.84 ms | 23.33 ms |
| 11cad11 | 1208.65 ms | 1250.88 ms | 42.23 ms |
| 2e5230b | 1207.41 ms | 1240.41 ms | 33.00 ms |
| 83bf9af | 1213.30 ms | 1234.18 ms | 20.89 ms |
| 1c9a029 | 1198.93 ms | 1233.94 ms | 35.00 ms |
| fe6228d | 1215.81 ms | 1234.04 ms | 18.23 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 39fbc4b | 24.14 KiB | 1.12 MiB | 1.09 MiB |
| 4c93fb8 | 24.14 KiB | 1.11 MiB | 1.09 MiB |
| 99e74a3 | 24.14 KiB | 1.12 MiB | 1.09 MiB |
| d52e416 | 24.14 KiB | 1.04 MiB | 1.02 MiB |
| 16b3235 | 24.14 KiB | 1.11 MiB | 1.09 MiB |
| 11cad11 | 24.14 KiB | 1.12 MiB | 1.10 MiB |
| 2e5230b | 24.14 KiB | 1.04 MiB | 1.02 MiB |
| 83bf9af | 24.14 KiB | 1.04 MiB | 1.02 MiB |
| 1c9a029 | 24.14 KiB | 1.10 MiB | 1.07 MiB |
| fe6228d | 24.14 KiB | 1.11 MiB | 1.08 MiB |
Previous results on branch: mobile-935/sdk-options
Startup times
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 340b451 | 1205.93 ms | 1225.39 ms | 19.45 ms |
| 56fb666 | 1215.11 ms | 1250.19 ms | 35.08 ms |
| 2816207 | 1228.90 ms | 1259.46 ms | 30.56 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 340b451 | 24.14 KiB | 1.13 MiB | 1.10 MiB |
| 56fb666 | 24.14 KiB | 1.13 MiB | 1.10 MiB |
| 2816207 | 24.14 KiB | 1.12 MiB | 1.10 MiB |
itaybre
left a comment
There was a problem hiding this comment.
Almost LGTM, just some small comments
And you will need to run make generate-public-api due to the new public APIs
cfc450a to
1d0cc82
Compare
Sentry Build Distribution
|
1d0cc82 to
037f0e4
Compare
Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift
Outdated
Show resolved
Hide resolved
Sentry Build Distribution
|
Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift
Outdated
Show resolved
Hide resolved
Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift
Outdated
Show resolved
Hide resolved
Implement SDK fields, setters and validation for network details capture: https://docs.sentry.io/platforms/javascript/session-replay/configuration/#network-details - String patterns for prefix matching (e.g., "https://api.example.com" matches subpaths) - NSRegularExpression patterns for complex regex matching - Deny list precedence over allow list - Empty string filtering to handle invalid input gracefully
…URL filtering Replace [Any] with [SentryUrlMatchable] for networkDetailAllowUrls/DenyUrls. Provides compile-time type safety in Swift while maintaining Objective-C compatibility through bridge properties. Follows the API pattern of SentryAttributeValue/Content.
…hables Already implemented in SentryUrlMatcher.convertFromAny, and the new impl had a bug flagged by SentryBot: #7580 (comment)
037f0e4 to
cad52c2
Compare
Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift
Outdated
Show resolved
Hide resolved
Sentry Build Distribution
|
#7580 (comment) Full ObjC support deferred to #7598. Added SentryReplayOptions#networkDetailHasUrls computed property for: 1) Confirming the feature is disabled in objc (see SentryReplayOptionsObjcTests.m) 2) Using higher up in stack (see SentryRRWebOptionsEvent, SentryNetworkTrackingIntegration.swift)
(ammend 1) re-run upon removal of objc networkDetailAllow|DenyUrls bridge
cad52c2 to
83310fd
Compare

Implement SDK fields, setters and validation for network details capture: https://docs.sentry.io/platforms/javascript/session-replay/configuration/#network-details
networkDetailAllowUrls(string|RegExp)[][]networkDetailDenyUrls(string|RegExp)[][]networkDetailAllowUrls.networkCaptureBodiesbooleantruenetworkDetailAllowUrls.networkRequestHeadersstring[][]networkDetailAllowUrls.networkResponseHeadersstring[][]networkDetailAllowUrls.networkDetail[Allow|Deny]Urlsnetwork[Request|Response]HeadersnetworkCaptureBodies📜 Description
PR 1/N. Extend SentryReplayOptions API with Session Replay Network Details configuration
PR 2/N. Adds test app UI to configure and test network details collection.
PR 3/N. Adds data holder classes to define structure of data being extracted
PR 4/N. Adds new swizzling introduced to capture response bodies.
PR 5/N. Implements extraction logic for headers & bodies.
PR 6/N. Hook into existing SentryNetworkTracker.m|h
PR 7/N. Implement conversion from breadcrumb data -> Session Replay compatible RRWebEvent
💡 Motivation and Context
Parent issue (android, cocoa, RN) - getsentry/sentry#84596
Cocoa sub-issue - #4944
This PR adds the SDK fields required for developers to enable network details extraction for network requests made during a session replay capture, by following the impl in sentry-javascript and sentry-java (android).
💚 How did you test it?
Unit tests
SentryReplayOptionsTests
SentryReplayOptionsNetworkTests
Additional unit tests for network details (I didn't put them in SentryReplayOptionsTests to avoid over-crowding that file / I assumed SentryReplayOptionsTests should be for high level testing of SentryReplayOptions).
SentryReplayOptionsObjcTests
ObjC <> Swift compatibility tests. Mostly for Regex matching
📝 Checklist
You have to check all boxes before merging:
sendDefaultPIIis enabled. Nothing extracted in this PR - SDKOptions available but no backing implementation.