From a1627711506103f173a34939e8b94677d41f9fc0 Mon Sep 17 00:00:00 2001 From: Max Chuquimia <> Date: Tue, 14 May 2024 07:58:56 +1000 Subject: [PATCH 1/3] fix: Convert Swift extension to helper class for use by ObjC --- CHANGELOG.md | 1 + Sentry.xcodeproj/project.pbxproj | 16 +++++++-------- Sources/Sentry/SentryNetworkTracker.m | 4 ++-- .../Extensions/URLSessionTaskExtensions.swift | 19 ------------------ .../Swift/Tools/URLSessionTaskHelper.swift | 20 +++++++++++++++++++ ....swift => URLSessionTaskHelperTests.swift} | 14 ++++++------- 6 files changed, 38 insertions(+), 36 deletions(-) delete mode 100644 Sources/Swift/Extensions/URLSessionTaskExtensions.swift create mode 100644 Sources/Swift/Tools/URLSessionTaskHelper.swift rename Tests/SentryTests/{Swift/Extensions/URLSessionTaskTests.swift => URLSessionTaskHelperTests.swift} (77%) diff --git a/CHANGELOG.md b/CHANGELOG.md index da4d71882d5..22e4c66fdb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Features - Add SIGTERM support ([#3895](https://github.com/getsentry/sentry-cocoa/pull/3895)) +- Fix retrieving GraphQL operation names crashing ([#3973](https://github.com/getsentry/sentry-cocoa/pull/3973)) ### Fixes diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index 6d7331abdf5..e089100eecb 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -72,8 +72,8 @@ 15E0A8F22411A45A00F044E3 /* SentrySession.m in Sources */ = {isa = PBXBuildFile; fileRef = 15E0A8F12411A45A00F044E3 /* SentrySession.m */; }; 33042A0D29DAF79A00C60085 /* SentryExtraContextProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 33042A0C29DAF79A00C60085 /* SentryExtraContextProvider.m */; }; 33042A1729DC2C4300C60085 /* SentryExtraContextProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33042A1629DC2C4300C60085 /* SentryExtraContextProviderTests.swift */; }; - 51B15F7E2BE88A7C0026A2F2 /* URLSessionTaskExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B15F7D2BE88A7C0026A2F2 /* URLSessionTaskExtensions.swift */; }; - 51B15F802BE88D510026A2F2 /* URLSessionTaskTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B15F7F2BE88D510026A2F2 /* URLSessionTaskTests.swift */; }; + 51B15F7E2BE88A7C0026A2F2 /* URLSessionTaskHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B15F7D2BE88A7C0026A2F2 /* URLSessionTaskHelper.swift */; }; + 51B15F802BE88D510026A2F2 /* URLSessionTaskHelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B15F7F2BE88D510026A2F2 /* URLSessionTaskHelperTests.swift */; }; 620379DB2AFE1415005AC0C1 /* SentryBuildAppStartSpans.h in Headers */ = {isa = PBXBuildFile; fileRef = 620379DA2AFE1415005AC0C1 /* SentryBuildAppStartSpans.h */; }; 620379DD2AFE1432005AC0C1 /* SentryBuildAppStartSpans.m in Sources */ = {isa = PBXBuildFile; fileRef = 620379DC2AFE1432005AC0C1 /* SentryBuildAppStartSpans.m */; }; 621D9F2F2B9B0320003D94DE /* SentryCurrentDateProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621D9F2E2B9B0320003D94DE /* SentryCurrentDateProvider.swift */; }; @@ -1035,8 +1035,8 @@ 33042A0B29DAF5F400C60085 /* SentryExtraContextProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SentryExtraContextProvider.h; sourceTree = ""; }; 33042A0C29DAF79A00C60085 /* SentryExtraContextProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryExtraContextProvider.m; sourceTree = ""; }; 33042A1629DC2C4300C60085 /* SentryExtraContextProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryExtraContextProviderTests.swift; sourceTree = ""; }; - 51B15F7D2BE88A7C0026A2F2 /* URLSessionTaskExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLSessionTaskExtensions.swift; sourceTree = ""; }; - 51B15F7F2BE88D510026A2F2 /* URLSessionTaskTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSessionTaskTests.swift; sourceTree = ""; }; + 51B15F7D2BE88A7C0026A2F2 /* URLSessionTaskHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLSessionTaskHelper.swift; sourceTree = ""; }; + 51B15F7F2BE88D510026A2F2 /* URLSessionTaskHelperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSessionTaskHelperTests.swift; sourceTree = ""; }; 620379DA2AFE1415005AC0C1 /* SentryBuildAppStartSpans.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryBuildAppStartSpans.h; path = include/SentryBuildAppStartSpans.h; sourceTree = ""; }; 620379DC2AFE1432005AC0C1 /* SentryBuildAppStartSpans.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryBuildAppStartSpans.m; sourceTree = ""; }; 621D9F2E2B9B0320003D94DE /* SentryCurrentDateProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCurrentDateProvider.swift; sourceTree = ""; }; @@ -2104,7 +2104,6 @@ isa = PBXGroup; children = ( 62872B622BA1B86100A4FA7D /* NSLockTests.swift */, - 51B15F7F2BE88D510026A2F2 /* URLSessionTaskTests.swift */, ); path = Extensions; sourceTree = ""; @@ -3628,6 +3627,7 @@ D8AFC0582BDA899A00118BE1 /* RedactRegionTests.swift */, D8F67AEF2BE0D31A00C9197B /* UIImageHelperTests.swift */, D8F67AF22BE10F7600C9197B /* UIRedactBuilderTests.swift */, + 51B15F7F2BE88D510026A2F2 /* URLSessionTaskHelperTests.swift */, ); name = Tools; sourceTree = ""; @@ -3659,6 +3659,7 @@ D8AFC0192BD7A20B00118BE1 /* SentryViewScreenshotProvider.swift */, D8AFC0562BDA895400118BE1 /* UIRedactBuilder.swift */, D8F67AED2BE0D19200C9197B /* UIImageHelper.swift */, + 51B15F7D2BE88A7C0026A2F2 /* URLSessionTaskHelper.swift */, ); path = Tools; sourceTree = ""; @@ -3817,7 +3818,6 @@ children = ( D8F016B52B962548007B9AFB /* StringExtensions.swift */, 62872B5E2BA1B7F300A4FA7D /* NSLock.swift */, - 51B15F7D2BE88A7C0026A2F2 /* URLSessionTaskExtensions.swift */, ); path = Extensions; sourceTree = ""; @@ -4424,7 +4424,7 @@ 7B3B473825D6CC7E00D01640 /* SentryNSError.m in Sources */, D8ACE3C82762187200F5A213 /* SentryNSDataTracker.m in Sources */, 7BE3C77D2446112C00A38442 /* SentryRateLimitParser.m in Sources */, - 51B15F7E2BE88A7C0026A2F2 /* URLSessionTaskExtensions.swift in Sources */, + 51B15F7E2BE88A7C0026A2F2 /* URLSessionTaskHelper.swift in Sources */, D8B088B729C9E3FF00213258 /* SentryTracerConfiguration.m in Sources */, 8ECC674A25C23A20000E2BF6 /* SentryTransactionContext.mm in Sources */, 03BCC38C27E1C01A003232C7 /* SentryTime.mm in Sources */, @@ -4763,7 +4763,7 @@ 63FE721420DA66EC00CDBAE8 /* SentryCrashMemory_Tests.m in Sources */, 62885DA729E946B100554F38 /* TestConncurrentModifications.swift in Sources */, 63FE720520DA66EC00CDBAE8 /* FileBasedTestCase.m in Sources */, - 51B15F802BE88D510026A2F2 /* URLSessionTaskTests.swift in Sources */, + 51B15F802BE88D510026A2F2 /* URLSessionTaskHelperTests.swift in Sources */, 63EED6C32237989300E02400 /* SentryOptionsTest.m in Sources */, 7BBD18B22451804C00427C76 /* SentryRetryAfterHeaderParserTests.swift in Sources */, 7BD337E424A356180050DB6E /* SentryCrashIntegrationTests.swift in Sources */, diff --git a/Sources/Sentry/SentryNetworkTracker.m b/Sources/Sentry/SentryNetworkTracker.m index 93287f991c6..54c99d2ccb6 100644 --- a/Sources/Sentry/SentryNetworkTracker.m +++ b/Sources/Sentry/SentryNetworkTracker.m @@ -452,7 +452,7 @@ - (void)captureFailedRequests:(NSURLSessionTask *)sessionTask context[@"response"] = response; if (self.isGraphQLOperationTrackingEnabled) { - context[@"graphql_operation_name"] = [sessionTask getGraphQLOperationName]; + context[@"graphql_operation_name"] = [URLSessionTaskHelper getGraphQLOperationNameFrom:sessionTask]; } event.context = context; @@ -506,7 +506,7 @@ - (void)addBreadcrumbForSessionTask:(NSURLSessionTask *)sessionTask [NSHTTPURLResponse localizedStringForStatusCode:responseStatusCode]; if (self.isGraphQLOperationTrackingEnabled) { - breadcrumbData[@"graphql_operation_name"] = [sessionTask getGraphQLOperationName]; + breadcrumbData[@"graphql_operation_name"] = [URLSessionTaskHelper getGraphQLOperationNameFrom:sessionTask]; } } diff --git a/Sources/Swift/Extensions/URLSessionTaskExtensions.swift b/Sources/Swift/Extensions/URLSessionTaskExtensions.swift deleted file mode 100644 index acf7bda79f0..00000000000 --- a/Sources/Swift/Extensions/URLSessionTaskExtensions.swift +++ /dev/null @@ -1,19 +0,0 @@ -import Foundation - -public extension URLSessionTask { - - @objc - func getGraphQLOperationName() -> String? { - guard originalRequest?.value(forHTTPHeaderField: "Content-Type") == "application/json" else { return nil } - guard let requestBody = originalRequest?.httpBody else { return nil } - - let requestInfo = try? JSONDecoder().decode(GraphQLRequest.self, from: requestBody) - - return requestInfo?.operationName - } - -} - -private struct GraphQLRequest: Decodable { - let operationName: String -} diff --git a/Sources/Swift/Tools/URLSessionTaskHelper.swift b/Sources/Swift/Tools/URLSessionTaskHelper.swift new file mode 100644 index 00000000000..198f12a04d5 --- /dev/null +++ b/Sources/Swift/Tools/URLSessionTaskHelper.swift @@ -0,0 +1,20 @@ +import Foundation + +@objcMembers +public class URLSessionTaskHelper: NSObject { + + static func getGraphQLOperationName(from task: URLSessionTask?) -> String? { + guard let task = task else { return nil } + guard task.originalRequest?.value(forHTTPHeaderField: "Content-Type") == "application/json" else { return nil } + guard let requestBody = task.originalRequest?.httpBody else { return nil } + + let requestInfo = try? JSONDecoder().decode(GraphQLRequest.self, from: requestBody) + + return requestInfo?.operationName + } + +} + +private struct GraphQLRequest: Decodable { + let operationName: String +} diff --git a/Tests/SentryTests/Swift/Extensions/URLSessionTaskTests.swift b/Tests/SentryTests/URLSessionTaskHelperTests.swift similarity index 77% rename from Tests/SentryTests/Swift/Extensions/URLSessionTaskTests.swift rename to Tests/SentryTests/URLSessionTaskHelperTests.swift index bc97e3ab648..89778345808 100644 --- a/Tests/SentryTests/Swift/Extensions/URLSessionTaskTests.swift +++ b/Tests/SentryTests/URLSessionTaskHelperTests.swift @@ -3,7 +3,7 @@ import Nimble @testable import Sentry import XCTest -final class URLSessionTaskTests: XCTestCase { +final class URLSessionTaskHelperTests: XCTestCase { func testHTTPContentTypeInvalid() { let task = makeTask( @@ -11,8 +11,8 @@ final class URLSessionTaskTests: XCTestCase { body: "8J+YiQo=" ) - let operationName = task.getGraphQLOperationName() - + let operationName = URLSessionTaskHelper.getGraphQLOperationName(from: task) + expect(operationName) == nil } @@ -22,7 +22,7 @@ final class URLSessionTaskTests: XCTestCase { body: "not json" ) - let operationName = task.getGraphQLOperationName() + let operationName = URLSessionTaskHelper.getGraphQLOperationName(from: task) expect(operationName) == nil } @@ -33,7 +33,7 @@ final class URLSessionTaskTests: XCTestCase { body: nil ) - let operationName = task.getGraphQLOperationName() + let operationName = URLSessionTaskHelper.getGraphQLOperationName(from: task) expect(operationName) == nil } @@ -52,14 +52,14 @@ final class URLSessionTaskTests: XCTestCase { """ ) - let operationName = task.getGraphQLOperationName() + let operationName = URLSessionTaskHelper.getGraphQLOperationName(from: task) expect(operationName) == "MyOperation" } } -private extension URLSessionTaskTests { +private extension URLSessionTaskHelperTests { func makeTask(headers: [String: String], body: String?) -> URLSessionTask { var request = URLRequest(url: URL(string: "https://anything.com")!) From 12df5afcf8c342d98c12c4b4f42b8d411e3bfdd8 Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Tue, 14 May 2024 10:46:10 +0200 Subject: [PATCH 2/3] changelog --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22e4c66fdb2..c166181b7e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,16 @@ # Changelog +## Unreleased + +### Fixes + +- Fix retrieving GraphQL operation names crashing ([#3973](https://github.com/getsentry/sentry-cocoa/pull/3973)) + ## 8.26.0 ### Features - Add SIGTERM support ([#3895](https://github.com/getsentry/sentry-cocoa/pull/3895)) -- Fix retrieving GraphQL operation names crashing ([#3973](https://github.com/getsentry/sentry-cocoa/pull/3973)) ### Fixes From b3a6377f55017760a1459ef4488b2392bd30d3db Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Tue, 14 May 2024 10:50:49 +0200 Subject: [PATCH 3/3] remove public --- Sources/Sentry/SentryNetworkTracker.m | 6 ++++-- Sources/Swift/Tools/URLSessionTaskHelper.swift | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Sources/Sentry/SentryNetworkTracker.m b/Sources/Sentry/SentryNetworkTracker.m index 54c99d2ccb6..71c577a3ee5 100644 --- a/Sources/Sentry/SentryNetworkTracker.m +++ b/Sources/Sentry/SentryNetworkTracker.m @@ -452,7 +452,8 @@ - (void)captureFailedRequests:(NSURLSessionTask *)sessionTask context[@"response"] = response; if (self.isGraphQLOperationTrackingEnabled) { - context[@"graphql_operation_name"] = [URLSessionTaskHelper getGraphQLOperationNameFrom:sessionTask]; + context[@"graphql_operation_name"] = + [URLSessionTaskHelper getGraphQLOperationNameFrom:sessionTask]; } event.context = context; @@ -506,7 +507,8 @@ - (void)addBreadcrumbForSessionTask:(NSURLSessionTask *)sessionTask [NSHTTPURLResponse localizedStringForStatusCode:responseStatusCode]; if (self.isGraphQLOperationTrackingEnabled) { - breadcrumbData[@"graphql_operation_name"] = [URLSessionTaskHelper getGraphQLOperationNameFrom:sessionTask]; + breadcrumbData[@"graphql_operation_name"] = + [URLSessionTaskHelper getGraphQLOperationNameFrom:sessionTask]; } } diff --git a/Sources/Swift/Tools/URLSessionTaskHelper.swift b/Sources/Swift/Tools/URLSessionTaskHelper.swift index 198f12a04d5..6018e1df7b2 100644 --- a/Sources/Swift/Tools/URLSessionTaskHelper.swift +++ b/Sources/Swift/Tools/URLSessionTaskHelper.swift @@ -1,7 +1,7 @@ import Foundation @objcMembers -public class URLSessionTaskHelper: NSObject { +class URLSessionTaskHelper: NSObject { static func getGraphQLOperationName(from task: URLSessionTask?) -> String? { guard let task = task else { return nil }