diff --git a/CHANGELOG.md b/CHANGELOG.md index bec657a6925..2f0cf044c83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Features +- Add start time to network request breadcrumbs (#4008) - Add C++ exception support for `__cxa_rethrow` (#3996) ### Improvements diff --git a/Sources/Sentry/SentryNetworkTracker.m b/Sources/Sentry/SentryNetworkTracker.m index 71c577a3ee5..a2f933b59cc 100644 --- a/Sources/Sentry/SentryNetworkTracker.m +++ b/Sources/Sentry/SentryNetworkTracker.m @@ -220,6 +220,10 @@ - (void)urlSessionTaskResume:(NSURLSessionTask *)sessionTask @"SentryNetworkTracker automatically started HTTP span for sessionTask: %@", netSpan.description); + // Register request start date in the sessionTask to use for breadcrumb + objc_setAssociatedObject(sessionTask, &SENTRY_NETWORK_REQUEST_START_DATE, [NSDate date], + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + objc_setAssociatedObject(sessionTask, &SENTRY_NETWORK_REQUEST_TRACKER_SPAN, netSpan, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @@ -484,6 +488,8 @@ - (void)addBreadcrumbForSessionTask:(NSURLSessionTask *)sessionTask [hasBreadcrumb boolValue]) { return; } + NSDate *requestStart + = objc_getAssociatedObject(sessionTask, &SENTRY_NETWORK_REQUEST_START_DATE); SentryLevel breadcrumbLevel = sessionTask.error != nil ? kSentryLevelError : kSentryLevelInfo; SentryBreadcrumb *breadcrumb = [[SentryBreadcrumb alloc] initWithLevel:breadcrumbLevel @@ -495,6 +501,7 @@ - (void)addBreadcrumbForSessionTask:(NSURLSessionTask *)sessionTask NSMutableDictionary *breadcrumbData = [NSMutableDictionary new]; breadcrumbData[@"url"] = urlComponents.sanitizedUrl; breadcrumbData[@"method"] = sessionTask.currentRequest.HTTPMethod; + breadcrumbData[@"request_start"] = requestStart; breadcrumbData[@"request_body_size"] = [NSNumber numberWithLongLong:sessionTask.countOfBytesSent]; breadcrumbData[@"response_body_size"] = diff --git a/Sources/Sentry/include/SentryNetworkTracker.h b/Sources/Sentry/include/SentryNetworkTracker.h index e0aa040da81..e24ef161cc7 100644 --- a/Sources/Sentry/include/SentryNetworkTracker.h +++ b/Sources/Sentry/include/SentryNetworkTracker.h @@ -6,6 +6,7 @@ NS_ASSUME_NONNULL_BEGIN static NSString *const SENTRY_NETWORK_REQUEST_OPERATION = @"http.client"; static NSString *const SENTRY_NETWORK_REQUEST_TRACKER_SPAN = @"SENTRY_NETWORK_REQUEST_TRACKER_SPAN"; +static NSString *const SENTRY_NETWORK_REQUEST_START_DATE = @"SENTRY_NETWORK_REQUEST_START_DATE"; static NSString *const SENTRY_NETWORK_REQUEST_TRACKER_BREADCRUMB = @"SENTRY_NETWORK_REQUEST_TRACKER_BREADCRUMB"; diff --git a/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift b/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift index 96cbc56aaa5..fa3f43b2ac6 100644 --- a/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift +++ b/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift @@ -338,6 +338,8 @@ class SentryNetworkTrackerTests: XCTestCase { XCTAssertEqual(breadcrumb!.data!["response_body_size"] as! Int64, DATA_BYTES_RECEIVED) XCTAssertEqual(breadcrumb!.data!["http.query"] as? String, "query=value&query2=value2") XCTAssertEqual(breadcrumb!.data!["http.fragment"] as? String, "fragment") + XCTAssertNotNil(breadcrumb!.data!["request_start"]) + XCTAssertTrue(breadcrumb!.data!["request_start"] is Date) XCTAssertNil(breadcrumb!.data!["graphql_operation_name"]) }