-
-
Notifications
You must be signed in to change notification settings - Fork 329
/
SentryUIEventTrackerTransactionMode.m
124 lines (101 loc) · 4.75 KB
/
SentryUIEventTrackerTransactionMode.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#import <SentryUIEventTrackerTransactionMode.h>
#if SENTRY_HAS_UIKIT
# import <SentryDependencyContainer.h>
# import <SentryHub+Private.h>
# import <SentryLog.h>
# import <SentrySDK+Private.h>
# import <SentrySDK.h>
# import <SentryScope.h>
# import <SentrySpanId.h>
# import <SentrySpanOperations.h>
# import <SentryTraceOrigins.h>
# import <SentryTracer.h>
# import <SentryTransactionContext+Private.h>
NS_ASSUME_NONNULL_BEGIN
@interface
SentryUIEventTrackerTransactionMode ()
@property (nonatomic, strong) SentryDispatchQueueWrapper *dispatchQueueWrapper;
@property (nonatomic, assign) NSTimeInterval idleTimeout;
@property (nullable, nonatomic, strong) NSMutableArray<SentryTracer *> *activeTransactions;
@end
@implementation SentryUIEventTrackerTransactionMode
- (instancetype)initWithDispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper
idleTimeout:(NSTimeInterval)idleTimeout
{
if (self = [super init]) {
self.dispatchQueueWrapper = dispatchQueueWrapper;
self.idleTimeout = idleTimeout;
self.activeTransactions = [NSMutableArray new];
}
return self;
}
- (void)handleUIEvent:(NSString *)action
operation:(NSString *)operation
accessibilityIdentifier:(NSString *)accessibilityIdentifier
{
// There might be more active transactions stored, but only the last one might still be
// active with a timeout. The others are already waiting for their children to finish
// without a timeout.
SentryTracer *currentActiveTransaction;
@synchronized(self.activeTransactions) {
currentActiveTransaction = self.activeTransactions.lastObject;
}
BOOL sameAction = [currentActiveTransaction.transactionContext.name isEqualToString:action];
if (sameAction) {
SENTRY_LOG_DEBUG(@"Dispatching idle timeout for transaction with span id %@",
currentActiveTransaction.spanId.sentrySpanIdString);
[currentActiveTransaction dispatchIdleTimeout];
return;
}
[currentActiveTransaction finish];
if (currentActiveTransaction) {
SENTRY_LOG_DEBUG(@"Finished transaction %@ (span ID %@)",
currentActiveTransaction.transactionContext.name,
currentActiveTransaction.spanId.sentrySpanIdString);
}
SentryTransactionContext *context =
[[SentryTransactionContext alloc] initWithName:action
nameSource:kSentryTransactionNameSourceComponent
operation:operation
origin:SentryTraceOriginUIEventTracker];
__block SentryTracer *transaction;
[SentrySDK.currentHub.scope useSpan:^(id<SentrySpan> _Nullable span) {
BOOL ongoingScreenLoadTransaction
= span != nil && [span.operation isEqualToString:SentrySpanOperationUILoad];
BOOL ongoingManualTransaction = span != nil
&& ![span.operation isEqualToString:SentrySpanOperationUILoad]
&& ![span.operation containsString:SentrySpanOperationUIAction];
BOOL bindToScope = !ongoingScreenLoadTransaction && !ongoingManualTransaction;
transaction = [SentrySDK.currentHub
startTransactionWithContext:context
bindToScope:bindToScope
customSamplingContext:@{}
configuration:[SentryTracerConfiguration configurationWithBlock:^(
SentryTracerConfiguration *config) {
config.idleTimeout = self.idleTimeout;
config.waitForChildren = YES;
config.dispatchQueueWrapper = self.dispatchQueueWrapper;
}]];
SENTRY_LOG_DEBUG(@"Automatically started a new transaction with name: "
@"%@, bindToScope: %@",
action, bindToScope ? @"YES" : @"NO");
}];
if (accessibilityIdentifier) {
[transaction setTagValue:accessibilityIdentifier forKey:@"accessibilityIdentifier"];
}
transaction.finishCallback = ^(SentryTracer *tracer) {
@synchronized(self.activeTransactions) {
[self.activeTransactions removeObject:tracer];
SENTRY_LOG_DEBUG(@"Active transactions after removing tracer for span ID %@: %@",
tracer.spanId.sentrySpanIdString, self.activeTransactions);
}
};
@synchronized(self.activeTransactions) {
SENTRY_LOG_DEBUG(@"Adding transaction %@ to list of active transactions (currently %@)",
transaction.spanId.sentrySpanIdString, self.activeTransactions);
[self.activeTransactions addObject:transaction];
}
}
@end
NS_ASSUME_NONNULL_END
#endif // SENTRY_HAS_UIKIT