Skip to content

Commit 687ccf6

Browse files
ref: Move trace propagation to its own class (#6337)
Extract the trace propagation logic into its own class, so its easier to test and maintain.
1 parent fa9a4bb commit 687ccf6

File tree

7 files changed

+148
-110
lines changed

7 files changed

+148
-110
lines changed

Sentry.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@
143143
62E2119A2DAE99FC007D7262 /* SentryAsyncSafeLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 62E211992DAE99FC007D7262 /* SentryAsyncSafeLog.m */; };
144144
62E300942D5202890037AA3F /* SentryExceptionCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E300932D5202830037AA3F /* SentryExceptionCodable.swift */; };
145145
62E5325B2DEEC862000B2DD5 /* TestCurrentDateProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 624729172DE5980500DFEE00 /* TestCurrentDateProviderTests.swift */; };
146+
62E59A532E8FB70000DB7A7B /* SentryTracePropagation.h in Headers */ = {isa = PBXBuildFile; fileRef = 62E59A522E8FB70000DB7A7B /* SentryTracePropagation.h */; };
147+
62E59A5A2E8FB85300DB7A7B /* SentryTracePropagation.m in Sources */ = {isa = PBXBuildFile; fileRef = 62E59A592E8FB85300DB7A7B /* SentryTracePropagation.m */; };
146148
62E75EB92E152953002EC91B /* InvocationsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E75EB82E152953002EC91B /* InvocationsTests.swift */; };
147149
62EF86A12C626D39004E058B /* SentryANRTrackerV2Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621AE74E2C626CF70012E730 /* SentryANRTrackerV2Tests.swift */; };
148150
62F05D2B2C0DB1F100916E3F /* SentryLogTestHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 62F05D2A2C0DB1F100916E3F /* SentryLogTestHelper.m */; };
@@ -1377,6 +1379,8 @@
13771379
62E081AA29ED4322000F69FC /* SentryBreadcrumbTestDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryBreadcrumbTestDelegate.swift; sourceTree = "<group>"; };
13781380
62E211992DAE99FC007D7262 /* SentryAsyncSafeLog.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryAsyncSafeLog.m; sourceTree = "<group>"; };
13791381
62E300932D5202830037AA3F /* SentryExceptionCodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryExceptionCodable.swift; sourceTree = "<group>"; };
1382+
62E59A522E8FB70000DB7A7B /* SentryTracePropagation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryTracePropagation.h; path = include/SentryTracePropagation.h; sourceTree = "<group>"; };
1383+
62E59A592E8FB85300DB7A7B /* SentryTracePropagation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryTracePropagation.m; sourceTree = "<group>"; };
13801384
62E75EB82E152953002EC91B /* InvocationsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvocationsTests.swift; sourceTree = "<group>"; };
13811385
62F05D292C0DB1C800916E3F /* SentryLogTestHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SentryLogTestHelper.h; sourceTree = "<group>"; };
13821386
62F05D2A2C0DB1F100916E3F /* SentryLogTestHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryLogTestHelper.m; sourceTree = "<group>"; };
@@ -3714,6 +3718,8 @@
37143718
8E564AE5267AF22600FE117D /* SentryNetworkTrackingIntegration.m */,
37153719
8E564AEC267AF24400FE117D /* SentryNetworkTracker.h */,
37163720
8E564AE7267AF22600FE117D /* SentryNetworkTracker.m */,
3721+
62E59A522E8FB70000DB7A7B /* SentryTracePropagation.h */,
3722+
62E59A592E8FB85300DB7A7B /* SentryTracePropagation.m */,
37173723
D8370B6B273DF20F00F66E2D /* SentryNSURLSessionTaskSearch.h */,
37183724
D8370B68273DF1E900F66E2D /* SentryNSURLSessionTaskSearch.m */,
37193725
A8F17B332902870300990B25 /* SentryHttpStatusCodeRange.m */,
@@ -5071,6 +5077,7 @@
50715077
84A305572BC9EF8C00D84283 /* SentryTraceProfiler.h in Headers */,
50725078
FA034AC82DD3DB4900FE3107 /* SentryIntegrationProtocol.h in Headers */,
50735079
63FE715720DA4C1100CDBAE8 /* SentryCrashThread.h in Headers */,
5080+
62E59A532E8FB70000DB7A7B /* SentryTracePropagation.h in Headers */,
50745081
7BF9EF862722D10600B5BBEF /* SentryTestObjCRuntimeWrapper.h in Headers */,
50755082
15360CD2243277A000112302 /* SentrySessionTracker.h in Headers */,
50765083
63FE718B20DA4C1100CDBAE8 /* SentryCrashReport.h in Headers */,
@@ -5954,6 +5961,7 @@
59545961
629194A92D51F976000F7C6B /* SentryDebugMetaCodable.swift in Sources */,
59555962
63FE714520DA4C1100CDBAE8 /* SentryCrashObjC.c in Sources */,
59565963
63FE710520DA4C1000CDBAE8 /* SentryAsyncSafeLog.c in Sources */,
5964+
62E59A5A2E8FB85300DB7A7B /* SentryTracePropagation.m in Sources */,
59575965
62E300942D5202890037AA3F /* SentryExceptionCodable.swift in Sources */,
59585966
0A2D8D5B289815C0008720F6 /* SentryBaseIntegration.m in Sources */,
59595967
639FCF991EBC7B9700778193 /* SentryEvent.m in Sources */,

Sources/Sentry/SentryNetworkTracker.m

Lines changed: 9 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#import "SentryTraceContext.h"
2828
#import "SentryTraceHeader.h"
2929
#import "SentryTraceOrigin.h"
30+
#import "SentryTracePropagation.h"
3031
#import "SentryTracer.h"
3132
#import "SentryUser.h"
3233
#import <objc/runtime.h>
@@ -107,35 +108,6 @@ - (void)disable SENTRY_DISABLE_THREAD_SANITIZER(SentryNetworkTrackerThreadSaniti
107108
_isGraphQLOperationTrackingEnabled = NO;
108109
}
109110

110-
- (BOOL)isTargetMatch:(NSURL *)URL withTargets:(NSArray *)targets
111-
{
112-
for (id targetCheck in targets) {
113-
if ([targetCheck isKindOfClass:[NSRegularExpression class]]) {
114-
NSString *string = URL.absoluteString;
115-
NSUInteger numberOfMatches =
116-
[targetCheck numberOfMatchesInString:string
117-
options:0
118-
range:NSMakeRange(0, [string length])];
119-
if (numberOfMatches > 0) {
120-
return YES;
121-
}
122-
} else if ([targetCheck isKindOfClass:[NSString class]]) {
123-
if ([URL.absoluteString containsString:targetCheck]) {
124-
return YES;
125-
}
126-
}
127-
}
128-
129-
return NO;
130-
}
131-
132-
- (BOOL)sessionTaskRequiresPropagation:(NSURLSessionTask *)sessionTask
133-
{
134-
return sessionTask.currentRequest != nil &&
135-
[self isTargetMatch:sessionTask.currentRequest.URL
136-
withTargets:SentrySDKInternal.options.tracePropagationTargets];
137-
}
138-
139111
- (void)urlSessionTaskResume:(NSURLSessionTask *)sessionTask
140112
{
141113
NSURLSessionTaskState sessionState = sessionTask.state;
@@ -217,7 +189,9 @@ - (void)urlSessionTaskResume:(NSURLSessionTask *)sessionTask
217189
}
218190

219191
SentryBaggage *baggage = [[[SentryTracer getTracer:span] traceContext] toBaggage];
220-
[self addBaggageHeader:baggage traceHeader:[netSpan toTraceHeader] toRequest:sessionTask];
192+
[SentryTracePropagation addBaggageHeader:baggage
193+
traceHeader:[netSpan toTraceHeader]
194+
toRequest:sessionTask];
221195

222196
SENTRY_LOG_DEBUG(
223197
@"SentryNetworkTracker automatically started HTTP span for sessionTask: %@",
@@ -249,66 +223,9 @@ - (void)addTraceWithoutTransactionToTask:(NSURLSessionTask *)sessionTask
249223
#endif
250224
replayId:SentrySDKInternal.currentHub.scope.replayId];
251225

252-
[self addBaggageHeader:[traceContext toBaggage]
253-
traceHeader:[propagationContext traceHeader]
254-
toRequest:sessionTask];
255-
}
256-
257-
- (void)addBaggageHeader:(SentryBaggage *)baggage
258-
traceHeader:(SentryTraceHeader *)traceHeader
259-
toRequest:(NSURLSessionTask *)sessionTask
260-
{
261-
if (![self sessionTaskRequiresPropagation:sessionTask]) {
262-
SENTRY_LOG_DEBUG(@"Not adding trace_id and baggage headers for %@",
263-
sessionTask.currentRequest.URL.absoluteString);
264-
return;
265-
}
266-
NSString *baggageHeader = @"";
267-
268-
if (baggage != nil) {
269-
NSDictionary *originalBaggage = [SentryBaggageSerialization
270-
decode:sessionTask.currentRequest.allHTTPHeaderFields[SENTRY_BAGGAGE_HEADER]];
271-
272-
if (originalBaggage[@"sentry-trace_id"] == nil) {
273-
baggageHeader = [baggage toHTTPHeaderWithOriginalBaggage:originalBaggage];
274-
}
275-
}
276-
277-
// First we check if the current request is mutable, so we could easily add a new
278-
// header. Otherwise we try to change the current request for a new one with the extra
279-
// header.
280-
if ([sessionTask.currentRequest isKindOfClass:[NSMutableURLRequest class]]) {
281-
NSMutableURLRequest *currentRequest = (NSMutableURLRequest *)sessionTask.currentRequest;
282-
283-
if ([currentRequest valueForHTTPHeaderField:SENTRY_TRACE_HEADER] == nil) {
284-
[currentRequest setValue:traceHeader.value forHTTPHeaderField:SENTRY_TRACE_HEADER];
285-
}
286-
287-
if (baggageHeader.length > 0) {
288-
[currentRequest setValue:baggageHeader forHTTPHeaderField:SENTRY_BAGGAGE_HEADER];
289-
}
290-
} else {
291-
// Even though NSURLSessionTask doesn't have 'setCurrentRequest', some subclasses
292-
// do. For those subclasses we replace the currentRequest with a mutable one with
293-
// the additional trace header. Since NSURLSessionTask is a public class and can be
294-
// override, we believe this is not considered a private api.
295-
SEL setCurrentRequestSelector = NSSelectorFromString(@"setCurrentRequest:");
296-
if ([sessionTask respondsToSelector:setCurrentRequestSelector]) {
297-
NSMutableURLRequest *newRequest = [sessionTask.currentRequest mutableCopy];
298-
299-
if ([newRequest valueForHTTPHeaderField:SENTRY_TRACE_HEADER] == nil) {
300-
[newRequest setValue:traceHeader.value forHTTPHeaderField:SENTRY_TRACE_HEADER];
301-
}
302-
303-
if (baggageHeader.length > 0) {
304-
[newRequest setValue:baggageHeader forHTTPHeaderField:SENTRY_BAGGAGE_HEADER];
305-
}
306-
307-
void (*func)(id, SEL, id param)
308-
= (void *)[sessionTask methodForSelector:setCurrentRequestSelector];
309-
func(sessionTask, setCurrentRequestSelector, newRequest);
310-
}
311-
}
226+
[SentryTracePropagation addBaggageHeader:[traceContext toBaggage]
227+
traceHeader:[propagationContext traceHeader]
228+
toRequest:sessionTask];
312229
}
313230

314231
- (void)urlSessionTask:(NSURLSessionTask *)sessionTask setState:(NSURLSessionTaskState)newState
@@ -401,8 +318,8 @@ - (void)captureFailedRequests:(NSURLSessionTask *)sessionTask
401318
return;
402319
}
403320

404-
if (![self isTargetMatch:myRequest.URL
405-
withTargets:SentrySDKInternal.options.failedRequestTargets]) {
321+
if (![SentryTracePropagation isTargetMatch:myRequest.URL
322+
withTargets:SentrySDKInternal.options.failedRequestTargets]) {
406323
SENTRY_LOG_DEBUG(
407324
@"Request url isn't within the request targets, not capturing HTTP Client errors.");
408325
return;
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#import <SentryBaggage.h>
2+
#import <SentryLogC.h>
3+
#import <SentrySDK+Private.h>
4+
#import <SentrySwift.h>
5+
#import <SentryTraceHeader.h>
6+
#import <SentryTracePropagation.h>
7+
8+
@implementation SentryTracePropagation
9+
10+
+ (void)addBaggageHeader:(SentryBaggage *)baggage
11+
traceHeader:(SentryTraceHeader *)traceHeader
12+
toRequest:(NSURLSessionTask *)sessionTask
13+
{
14+
if (![SentryTracePropagation sessionTaskRequiresPropagation:sessionTask]) {
15+
SENTRY_LOG_DEBUG(@"Not adding trace_id and baggage headers for %@",
16+
sessionTask.currentRequest.URL.absoluteString);
17+
return;
18+
}
19+
NSString *baggageHeader = @"";
20+
21+
if (baggage != nil) {
22+
NSDictionary *originalBaggage = [SentryBaggageSerialization
23+
decode:sessionTask.currentRequest.allHTTPHeaderFields[SENTRY_BAGGAGE_HEADER]];
24+
25+
if (originalBaggage[@"sentry-trace_id"] == nil) {
26+
baggageHeader = [baggage toHTTPHeaderWithOriginalBaggage:originalBaggage];
27+
}
28+
}
29+
30+
// First we check if the current request is mutable, so we could easily add a new
31+
// header. Otherwise we try to change the current request for a new one with the extra
32+
// header.
33+
if ([sessionTask.currentRequest isKindOfClass:[NSMutableURLRequest class]]) {
34+
NSMutableURLRequest *currentRequest = (NSMutableURLRequest *)sessionTask.currentRequest;
35+
36+
if ([currentRequest valueForHTTPHeaderField:SENTRY_TRACE_HEADER] == nil) {
37+
[currentRequest setValue:traceHeader.value forHTTPHeaderField:SENTRY_TRACE_HEADER];
38+
}
39+
40+
if (baggageHeader.length > 0) {
41+
[currentRequest setValue:baggageHeader forHTTPHeaderField:SENTRY_BAGGAGE_HEADER];
42+
}
43+
} else {
44+
// Even though NSURLSessionTask doesn't have 'setCurrentRequest', some subclasses
45+
// do. For those subclasses we replace the currentRequest with a mutable one with
46+
// the additional trace header. Since NSURLSessionTask is a public class and can be
47+
// override, we believe this is not considered a private api.
48+
SEL setCurrentRequestSelector = NSSelectorFromString(@"setCurrentRequest:");
49+
if ([sessionTask respondsToSelector:setCurrentRequestSelector]) {
50+
NSMutableURLRequest *newRequest = [sessionTask.currentRequest mutableCopy];
51+
52+
if ([newRequest valueForHTTPHeaderField:SENTRY_TRACE_HEADER] == nil) {
53+
[newRequest setValue:traceHeader.value forHTTPHeaderField:SENTRY_TRACE_HEADER];
54+
}
55+
56+
if (baggageHeader.length > 0) {
57+
[newRequest setValue:baggageHeader forHTTPHeaderField:SENTRY_BAGGAGE_HEADER];
58+
}
59+
60+
void (*func)(id, SEL, id param)
61+
= (void *)[sessionTask methodForSelector:setCurrentRequestSelector];
62+
func(sessionTask, setCurrentRequestSelector, newRequest);
63+
}
64+
}
65+
}
66+
67+
+ (BOOL)sessionTaskRequiresPropagation:(NSURLSessionTask *)sessionTask
68+
{
69+
return sessionTask.currentRequest != nil &&
70+
[SentryTracePropagation isTargetMatch:sessionTask.currentRequest.URL
71+
withTargets:SentrySDKInternal.options.tracePropagationTargets];
72+
}
73+
74+
+ (BOOL)isTargetMatch:(NSURL *)URL withTargets:(NSArray *)targets
75+
{
76+
for (id targetCheck in targets) {
77+
if ([targetCheck isKindOfClass:[NSRegularExpression class]]) {
78+
NSString *string = URL.absoluteString;
79+
NSUInteger numberOfMatches =
80+
[targetCheck numberOfMatchesInString:string
81+
options:0
82+
range:NSMakeRange(0, [string length])];
83+
if (numberOfMatches > 0) {
84+
return YES;
85+
}
86+
} else if ([targetCheck isKindOfClass:[NSString class]]) {
87+
if ([URL.absoluteString containsString:targetCheck]) {
88+
return YES;
89+
}
90+
}
91+
}
92+
93+
return NO;
94+
}
95+
96+
@end

Sources/Sentry/include/SentryNetworkTracker.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ static NSString *const SENTRY_NETWORK_REQUEST_TRACKER_BREADCRUMB
1919
- (void)enableNetworkBreadcrumbs;
2020
- (void)enableCaptureFailedRequests;
2121
- (void)enableGraphQLOperationTracking;
22-
- (BOOL)isTargetMatch:(NSURL *)URL withTargets:(NSArray *)targets;
2322
- (void)disable;
2423

2524
@property (nonatomic, readonly) BOOL isNetworkTrackingEnabled;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#import "SentryDefines.h"
2+
3+
NS_ASSUME_NONNULL_BEGIN
4+
5+
@class SentryBaggage;
6+
@class SentryTraceHeader;
7+
8+
@interface SentryTracePropagation : NSObject
9+
10+
+ (void)addBaggageHeader:(SentryBaggage *)baggage
11+
traceHeader:(SentryTraceHeader *)traceHeader
12+
toRequest:(NSURLSessionTask *)sessionTask;
13+
14+
+ (BOOL)isTargetMatch:(NSURL *)URL withTargets:(NSArray *)targets;
15+
16+
@end
17+
18+
NS_ASSUME_NONNULL_END

0 commit comments

Comments
 (0)