Skip to content

Commit 3965bfa

Browse files
committed
feat(network-details): Add NetworkRequestData -> breadcrumb -> RRBWebEvent
Add populated NetworkRequestData to breadcrumb data SentryNetworkTracker#addBreadcrumbForSessionTask Read NetworkRequestData from breadcrumb when converting for session replay SentrySRDefaultBreadcrumbConverter
1 parent fde4a5e commit 3965bfa

3 files changed

Lines changed: 69 additions & 0 deletions

File tree

Sources/Sentry/SentryNetworkTracker.m

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,15 @@ - (void)addBreadcrumbForSessionTask:(NSURLSessionTask *)sessionTask
481481
breadcrumbData[@"http.fragment"] = urlComponents.fragment;
482482
}
483483

484+
// Add network details if available for session replay
485+
SentryNetworkRequestData *networkRequestData
486+
= objc_getAssociatedObject(sessionTask, &SentryNetworkRequestDataKey);
487+
if (networkRequestData) {
488+
breadcrumbData[SentryReplayNetworkDetailsKey] = networkRequestData;
489+
SENTRY_LOG_DEBUG(@"[NetworkCapture] Added network details to breadcrumb: %@",
490+
[networkRequestData description]);
491+
}
492+
484493
breadcrumb.data = breadcrumbData;
485494
[SentrySDK addBreadcrumb:breadcrumb];
486495

Sources/Sentry/include/SentryPrivate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#import "SentryNSDataSwizzlingHelper.h"
2626
#import "SentryNSDataUtils.h"
2727
#import "SentryNSFileManagerSwizzlingHelper.h"
28+
#import "SentryNetworkRequestData.h"
2829
#import "SentryNetworkTracker.h"
2930
#import "SentrySDK+Private.h"
3031
#import "SentryScope+Private.h"

Sources/Swift/Integrations/SessionReplay/SentrySRDefaultBreadcrumbConverter.swift

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,67 @@ import Foundation
8080
data[newKey.snakeToCamelCase()] = value
8181
})
8282

83+
// Add Network Details data when available
84+
if let networkRequestData = breadcrumb.data?["_networkDetails"] as? SentryNetworkRequestData {
85+
addNetworkDetails(from: networkRequestData, to: &data)
86+
}
87+
8388
//We dont have end of the request in the breadcrumb.
8489
return SentryRRWebSpanEvent(timestamp: startTimestamp, endTimestamp: timestamp, operation: "resource.http", description: description, data: data)
8590
}
91+
92+
private func addNetworkDetails(from networkRequestData: SentryNetworkRequestData, to data: inout [String: Any]) {
93+
let networkData = networkRequestData.serialize()
94+
95+
// Add top-level network metadata
96+
if let method = networkData["method"] as? String {
97+
data["method"] = method
98+
}
99+
if let statusCode = networkData["statusCode"] as? NSNumber {
100+
data["statusCode"] = statusCode
101+
}
102+
if let requestBodySize = networkData["requestBodySize"] as? NSNumber {
103+
data["requestBodySize"] = requestBodySize
104+
}
105+
if let responseBodySize = networkData["responseBodySize"] as? NSNumber {
106+
data["responseBodySize"] = responseBodySize
107+
}
108+
109+
// Process request and response details using shared logic
110+
if let request = networkData["request"] as? [String: Any] {
111+
if let requestData = processRequestOrResponseData(request), !requestData.isEmpty {
112+
data["request"] = requestData
113+
}
114+
}
115+
116+
if let response = networkData["response"] as? [String: Any] {
117+
if let responseData = processRequestOrResponseData(response), !responseData.isEmpty {
118+
data["response"] = responseData
119+
}
120+
}
121+
}
122+
123+
private func processRequestOrResponseData(_ sourceData: [String: Any]) -> [String: Any]? {
124+
var result = [String: Any]()
125+
126+
if let size = sourceData["size"] as? NSNumber {
127+
result["size"] = size
128+
}
129+
130+
if let body = sourceData["body"] as? [String: Any] {
131+
if let bodyContent = body["body"] {
132+
result["body"] = bodyContent
133+
}
134+
if let warnings = body["warnings"] as? [String], !warnings.isEmpty {
135+
result["_meta"] = ["warnings": warnings]
136+
}
137+
}
138+
139+
if let headers = sourceData["headers"] as? [String: String], !headers.isEmpty {
140+
result["headers"] = headers
141+
}
142+
143+
return result.isEmpty ? nil : result
144+
}
86145
}
87146
// swiftlint:enable missing_docs

0 commit comments

Comments
 (0)