Skip to content

Commit fa0b660

Browse files
author
Max Chuquimia
committed
feat: Send GraphQL "operationName" in HTTP breadcrumbs
1 parent 42ef6ba commit fa0b660

File tree

8 files changed

+77
-0
lines changed

8 files changed

+77
-0
lines changed

Sentry.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@
7575
15E0A8F22411A45A00F044E3 /* SentrySession.m in Sources */ = {isa = PBXBuildFile; fileRef = 15E0A8F12411A45A00F044E3 /* SentrySession.m */; };
7676
33042A0D29DAF79A00C60085 /* SentryExtraContextProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 33042A0C29DAF79A00C60085 /* SentryExtraContextProvider.m */; };
7777
33042A1729DC2C4300C60085 /* SentryExtraContextProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33042A1629DC2C4300C60085 /* SentryExtraContextProviderTests.swift */; };
78+
5147B3752B50B5FA00129F4B /* NSURLSessionTask+Sentry.h in Headers */ = {isa = PBXBuildFile; fileRef = 5147B3732B50B5FA00129F4B /* NSURLSessionTask+Sentry.h */; };
79+
5147B3762B50B5FA00129F4B /* NSURLSessionTask+Sentry.m in Sources */ = {isa = PBXBuildFile; fileRef = 5147B3742B50B5FA00129F4B /* NSURLSessionTask+Sentry.m */; };
7880
620379DB2AFE1415005AC0C1 /* SentryBuildAppStartSpans.h in Headers */ = {isa = PBXBuildFile; fileRef = 620379DA2AFE1415005AC0C1 /* SentryBuildAppStartSpans.h */; };
7981
620379DD2AFE1432005AC0C1 /* SentryBuildAppStartSpans.m in Sources */ = {isa = PBXBuildFile; fileRef = 620379DC2AFE1432005AC0C1 /* SentryBuildAppStartSpans.m */; };
8082
622C08D829E546F4002571D4 /* SentryTraceOrigins.h in Headers */ = {isa = PBXBuildFile; fileRef = 622C08D729E546F4002571D4 /* SentryTraceOrigins.h */; };
@@ -993,6 +995,8 @@
993995
33042A0B29DAF5F400C60085 /* SentryExtraContextProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SentryExtraContextProvider.h; sourceTree = "<group>"; };
994996
33042A0C29DAF79A00C60085 /* SentryExtraContextProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryExtraContextProvider.m; sourceTree = "<group>"; };
995997
33042A1629DC2C4300C60085 /* SentryExtraContextProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryExtraContextProviderTests.swift; sourceTree = "<group>"; };
998+
5147B3732B50B5FA00129F4B /* NSURLSessionTask+Sentry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSURLSessionTask+Sentry.h"; path = "include/NSURLSessionTask+Sentry.h"; sourceTree = "<group>"; };
999+
5147B3742B50B5FA00129F4B /* NSURLSessionTask+Sentry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSURLSessionTask+Sentry.m"; path = "include/NSURLSessionTask+Sentry.m"; sourceTree = "<group>"; };
9961000
620379DA2AFE1415005AC0C1 /* SentryBuildAppStartSpans.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryBuildAppStartSpans.h; path = include/SentryBuildAppStartSpans.h; sourceTree = "<group>"; };
9971001
620379DC2AFE1432005AC0C1 /* SentryBuildAppStartSpans.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryBuildAppStartSpans.m; sourceTree = "<group>"; };
9981002
622C08D729E546F4002571D4 /* SentryTraceOrigins.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryTraceOrigins.h; path = include/SentryTraceOrigins.h; sourceTree = "<group>"; };
@@ -2045,6 +2049,8 @@
20452049
7B6438A926A70F24000D0F65 /* UIViewController+Sentry.m */,
20462050
0A2D8D9728997887008720F6 /* NSLocale+Sentry.h */,
20472051
0A2D8D9428997845008720F6 /* NSLocale+Sentry.m */,
2052+
5147B3732B50B5FA00129F4B /* NSURLSessionTask+Sentry.h */,
2053+
5147B3742B50B5FA00129F4B /* NSURLSessionTask+Sentry.m */,
20482054
);
20492055
name = Categories;
20502056
sourceTree = "<group>";
@@ -3752,6 +3758,7 @@
37523758
63FE716F20DA4C1100CDBAE8 /* SentryCrashCPU_Apple.h in Headers */,
37533759
639FCFA81EBC80CC00778193 /* SentryFrame.h in Headers */,
37543760
D8BFE37229A3782F002E73F3 /* SentryTimeToDisplayTracker.h in Headers */,
3761+
5147B3752B50B5FA00129F4B /* NSURLSessionTask+Sentry.h in Headers */,
37553762
8E8C57A625EEFC43001CEEFA /* SentryTracesSampler.h in Headers */,
37563763
7B634599280EB9D100CFA05A /* SentryUIEventTrackingIntegration.h in Headers */,
37573764
63FE716D20DA4C1100CDBAE8 /* SentryCrashSysCtl.h in Headers */,
@@ -4285,6 +4292,7 @@
42854292
7BA61CBB247BC5D800C130A8 /* SentryCrashDefaultBinaryImageProvider.m in Sources */,
42864293
63FE713120DA4C1100CDBAE8 /* SentryCrashDynamicLinker.c in Sources */,
42874294
8E25C95325F836D000DC215B /* SentryRandom.m in Sources */,
4295+
5147B3762B50B5FA00129F4B /* NSURLSessionTask+Sentry.m in Sources */,
42884296
7BC85231245812EC005A70F0 /* SentryFileContents.m in Sources */,
42894297
03F84D3527DD4191008FE43F /* SentryThreadHandle.cpp in Sources */,
42904298
0A2D8DA9289BC905008720F6 /* SentryViewHierarchy.m in Sources */,

Sources/Sentry/Public/SentryOptions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,12 @@ NS_SWIFT_NAME(Options)
140140
*/
141141
@property (nonatomic, assign) BOOL enableAutoSessionTracking;
142142

143+
/**
144+
* Whether to attach the top level `operationName` node of HTTP json requests to HTTP breadcrumbs
145+
* @note Default is @c NO.
146+
*/
147+
@property (nonatomic, assign) BOOL enableGraphQLOperationTracking;
148+
143149
/**
144150
* Whether to enable Watchdog Termination tracking or not.
145151
* @note This feature requires the @c SentryCrashIntegration being enabled, otherwise it would

Sources/Sentry/SentryNetworkTracker.m

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#import "SentryTraceOrigins.h"
2525
#import "SentryTracer.h"
2626
#import "SentryUser.h"
27+
#import "NSURLSessionTask+Sentry.h"
2728
#import <objc/runtime.h>
2829
@import SentryPrivate;
2930

@@ -42,6 +43,7 @@
4243
@property (nonatomic, assign) BOOL isNetworkTrackingEnabled;
4344
@property (nonatomic, assign) BOOL isNetworkBreadcrumbEnabled;
4445
@property (nonatomic, assign) BOOL isCaptureFailedRequestsEnabled;
46+
@property (nonatomic, assign) BOOL isGraphQLOperationTrackingEnabled;
4547

4648
@end
4749

@@ -61,6 +63,7 @@ - (instancetype)init
6163
_isNetworkTrackingEnabled = NO;
6264
_isNetworkBreadcrumbEnabled = NO;
6365
_isCaptureFailedRequestsEnabled = NO;
66+
_isGraphQLOperationTrackingEnabled = NO;
6467
}
6568
return self;
6669
}
@@ -86,12 +89,20 @@ - (void)enableCaptureFailedRequests
8689
}
8790
}
8891

92+
- (void)enableGraphQLOperationTracking
93+
{
94+
@synchronized(self) {
95+
_isGraphQLOperationTrackingEnabled = YES;
96+
}
97+
}
98+
8999
- (void)disable
90100
{
91101
@synchronized(self) {
92102
_isNetworkBreadcrumbEnabled = NO;
93103
_isNetworkTrackingEnabled = NO;
94104
_isCaptureFailedRequestsEnabled = NO;
105+
_isGraphQLOperationTrackingEnabled = NO;
95106
}
96107
}
97108

@@ -439,6 +450,11 @@ - (void)captureFailedRequests:(NSURLSessionTask *)sessionTask
439450
}
440451

441452
context[@"response"] = response;
453+
454+
if (self.isGraphQLOperationTrackingEnabled) {
455+
context[@"graphql"] = [sessionTask sentry_graphQLOperationName];
456+
}
457+
442458
event.context = context;
443459

444460
[SentrySDK captureEvent:event];
@@ -488,6 +504,10 @@ - (void)addBreadcrumbForSessionTask:(NSURLSessionTask *)sessionTask
488504
breadcrumbData[@"status_code"] = statusCode;
489505
breadcrumbData[@"reason"] =
490506
[NSHTTPURLResponse localizedStringForStatusCode:responseStatusCode];
507+
508+
if (self.isGraphQLOperationTrackingEnabled) {
509+
breadcrumbData[@"graphql"] = [sessionTask sentry_graphQLOperationName];
510+
}
491511
}
492512

493513
if (urlComponents.query != nil) {

Sources/Sentry/SentryNetworkTrackingIntegration.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ - (BOOL)installWithOptions:(SentryOptions *)options
2929
[SentryNetworkTracker.sharedInstance enableCaptureFailedRequests];
3030
}
3131

32+
if (options.enableGraphQLOperationTracking) {
33+
[SentryNetworkTracker.sharedInstance enableGraphQLOperationTracking];
34+
}
35+
3236
if (shouldEnableNetworkTracking || options.enableNetworkBreadcrumbs
3337
|| options.enableCaptureFailedRequests) {
3438
[SentryNetworkTrackingIntegration swizzleURLSessionTask];

Sources/Sentry/SentryOptions.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ - (instancetype)init
9999
_defaultSampleRate = @1;
100100
self.sampleRate = _defaultSampleRate;
101101
self.enableAutoSessionTracking = YES;
102+
self.enableGraphQLOperationTracking = NO;
102103
self.enableWatchdogTerminationTracking = YES;
103104
self.sessionTrackingIntervalMillis = [@30000 unsignedIntValue];
104105
self.attachStacktrace = YES;
@@ -352,6 +353,9 @@ - (BOOL)validateOptions:(NSDictionary<NSString *, id> *)options
352353
[self setBool:options[@"enableAutoSessionTracking"]
353354
block:^(BOOL value) { self->_enableAutoSessionTracking = value; }];
354355

356+
[self setBool:options[@"enableGraphQLOperationTracking"]
357+
block:^(BOOL value) { self->_enableGraphQLOperationTracking = value; }];
358+
355359
[self setBool:options[@"enableWatchdogTerminationTracking"]
356360
block:^(BOOL value) { self->_enableWatchdogTerminationTracking = value; }];
357361

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#import <Foundation/Foundation.h>
2+
3+
@interface
4+
NSURLSessionTask (Sentry)
5+
6+
- (nullable NSString *)sentry_graphQLOperationName;
7+
8+
@end
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#import "NSURLSessionTask+Sentry.h"
2+
3+
4+
@implementation
5+
NSURLSessionTask (Sentry)
6+
7+
- (nullable NSString *)sentry_graphQLOperationName
8+
{
9+
if (!self.originalRequest.HTTPBody) { return nil; }
10+
if (![[self.originalRequest valueForHTTPHeaderField:@"Content-Type"] isEqual: @"application/json"]) { return nil; }
11+
12+
NSError *error = nil;
13+
id requestDictionary = [NSJSONSerialization JSONObjectWithData:self.originalRequest.HTTPBody options:0 error:&error];
14+
15+
if (error) { return nil; }
16+
if (![requestDictionary isKindOfClass: [NSDictionary class]]) { return nil; } // Could be an array
17+
18+
id operationName = [requestDictionary valueForKey:@"operationName"];
19+
if (![operationName isKindOfClass: [NSString class]]) { return nil; }
20+
if ([operationName length] == 0) { return nil; }
21+
22+
return operationName;
23+
}
24+
25+
@end

Sources/Sentry/include/SentryNetworkTracker.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ static NSString *const SENTRY_NETWORK_REQUEST_TRACKER_BREADCRUMB
1818
- (void)enableNetworkTracking;
1919
- (void)enableNetworkBreadcrumbs;
2020
- (void)enableCaptureFailedRequests;
21+
- (void)enableGraphQLOperationTracking;
2122
- (BOOL)isTargetMatch:(NSURL *)URL withTargets:(NSArray *)targets;
2223
- (void)disable;
2324

2425
@property (nonatomic, readonly) BOOL isNetworkTrackingEnabled;
2526
@property (nonatomic, readonly) BOOL isNetworkBreadcrumbEnabled;
2627
@property (nonatomic, readonly) BOOL isCaptureFailedRequestsEnabled;
28+
@property (nonatomic, readonly) BOOL isGraphQLOperationTrackingEnabled;
2729

2830
@end
2931

0 commit comments

Comments
 (0)