Skip to content

Commit aac24ac

Browse files
authored
ref: Refactor performance tracker swift version (#6450)
1 parent 94de2d3 commit aac24ac

11 files changed

+99
-57
lines changed

Sources/Sentry/SentryDefaultUIViewControllerPerformanceTracker.m

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,15 @@
2020
# import <objc/runtime.h>
2121

2222
@interface SentryTimeToDisplayTracker () <SentryInitialDisplayReporting>
23+
@end
2324

25+
@interface SentrySwiftUISpanHelper () <SentryInitialDisplayReporting>
2426
@end
2527

2628
@interface SentryObjCSwiftUISpanHelper ()
29+
30+
@property (nonatomic, strong) id<SentryInitialDisplayReporting> initialDisplayReporting;
31+
2732
@end
2833

2934
@implementation SentryObjCSwiftUISpanHelper
@@ -38,6 +43,11 @@ - (instancetype)initWithHasSpan:(BOOL)hasSpan
3843
return self;
3944
}
4045

46+
- (void)reportInitialDisplay
47+
{
48+
[self.initialDisplayReporting reportInitialDisplay];
49+
}
50+
4151
@end
4252

4353
// In a previous implementation, we used associated objects to store the time to display tracker,
@@ -85,17 +95,12 @@ @interface SentryDefaultUIViewControllerPerformanceTracker ()
8595
@implementation SentryDefaultUIViewControllerPerformanceTracker
8696

8797
- (instancetype)initWithTracker:(SentryPerformanceTracker *)tracker
88-
dispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper
8998
{
9099
if (self = [super init]) {
91100
self.tracker = tracker;
92101

93-
SentryOptions *options = [SentrySDKInternal options];
94-
self.inAppLogic = [[SentryInAppLogic alloc] initWithInAppIncludes:options.inAppIncludes
95-
inAppExcludes:options.inAppExcludes];
96-
97102
_alwaysWaitForFullDisplay = NO;
98-
_dispatchQueueWrapper = dispatchQueueWrapper;
103+
_dispatchQueueWrapper = SentryDependencyContainer.sharedInstance.dispatchQueueWrapper;
99104

100105
_ttdTrackers = [[SentryWeakMap alloc] init];
101106
_spanIds = [[SentryWeakMap alloc] init];
@@ -106,9 +111,10 @@ - (instancetype)initWithTracker:(SentryPerformanceTracker *)tracker
106111
}
107112

108113
- (void)viewControllerLoadView:(UIViewController *)controller
114+
isInApp:(BOOL (^)(Class))isInApp
109115
callbackToOrigin:(void (^)(void))callbackToOrigin
110116
{
111-
if (![self.inAppLogic isClassInApp:[controller class]]) {
117+
if (!isInApp([controller class])) {
112118
SENTRY_LOG_DEBUG(
113119
@"Won't track view controller that is not part of the app bundle: %@.", controller);
114120
callbackToOrigin();
@@ -273,34 +279,34 @@ - (nullable SentryTimeToDisplayTracker *)startTimeToDisplayTrackerForScreen:(NSS
273279
return ttdTracker;
274280
}
275281

276-
- (SentrySwiftUISpanHelper *)startTimeToDisplayTrackerForScreen:(NSString *)screenName
277-
waitForFullDisplay:(BOOL)waitforFullDisplay
278-
transactionId:(SentrySpanId *)transactionId;
282+
- (SentryObjCSwiftUISpanHelper *)startTimeToDisplayTrackerForScreen:(NSString *)screenName
283+
waitForFullDisplay:(BOOL)waitforFullDisplay
284+
transactionId:(SentrySpanId *)transactionId;
279285
{
280286
id<SentrySpan> span = [SentryPerformanceTracker.shared getSpan:transactionId];
281287
if (span != nil && [span isKindOfClass:[SentryTracer class]]) {
282288
SentryTimeToDisplayTracker *displayReporting =
283289
[self startTimeToDisplayTrackerForScreen:screenName
284290
waitForFullDisplay:waitforFullDisplay
285291
tracer:(SentryTracer *)span];
286-
return [[SentrySwiftUISpanHelper alloc] initWithHasSpan:YES
287-
initialDisplayReporting:displayReporting];
292+
return [[SentryObjCSwiftUISpanHelper alloc] initWithHasSpan:YES
293+
initialDisplayReporting:displayReporting];
288294
}
289-
return [[SentrySwiftUISpanHelper alloc] initWithHasSpan:NO initialDisplayReporting:nil];
295+
return [[SentryObjCSwiftUISpanHelper alloc] initWithHasSpan:NO initialDisplayReporting:nil];
290296
}
291297

292298
+ (SentryObjCSwiftUISpanHelper *)startTimeToDisplayTrackerForScreen:(NSString *)screenName
293299
waitForFullDisplay:(BOOL)waitforFullDisplay
294-
transactionId:(SentrySpanId *)transactionId;
300+
transactionId:(SentrySpanId *)transactionId
295301
{
296-
id<SentryUIViewControllerPerformanceTracker> vcTracker
302+
SentryUIViewControllerPerformanceTracker *vcTracker
297303
= SentryDependencyContainer.sharedInstance.uiViewControllerPerformanceTracker;
298304
SentrySwiftUISpanHelper *result =
299305
[vcTracker startTimeToDisplayTrackerForScreen:screenName
300306
waitForFullDisplay:waitforFullDisplay
301307
transactionId:transactionId];
302308
return [[SentryObjCSwiftUISpanHelper alloc] initWithHasSpan:result.hasSpan
303-
initialDisplayReporting:result.initialDisplayReporting];
309+
initialDisplayReporting:result];
304310
}
305311

306312
- (void)viewControllerViewWillAppear:(UIViewController *)controller

Sources/Sentry/SentryDependencyContainer.m

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,6 @@ @interface SentryDefaultAppStateManager () <SentryAppStateManager>
6565
@interface SentryWatchdogTerminationScopeObserver () <SentryScopeObserver>
6666
@end
6767

68-
@interface SentryDefaultUIViewControllerPerformanceTracker () <
69-
SentryUIViewControllerPerformanceTracker>
70-
@end
71-
7268
@interface SentryDelayedFramesTracker () <SentryDelayedFramesTrackerWrapper>
7369
@end
7470
#endif
@@ -320,14 +316,12 @@ - (SentryViewHierarchyProvider *)viewHierarchyProvider SENTRY_THREAD_SANITIZER_D
320316
# endif // SENTRY_HAS_UIKIT
321317
}
322318

323-
- (id<SentryUIViewControllerPerformanceTracker>)
319+
- (SentryUIViewControllerPerformanceTracker *)
324320
uiViewControllerPerformanceTracker SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK
325321
{
326322
# if SENTRY_HAS_UIKIT
327323
SENTRY_LAZY_INIT(_uiViewControllerPerformanceTracker,
328-
[[SentryDefaultUIViewControllerPerformanceTracker alloc]
329-
initWithTracker:SentryPerformanceTracker.shared
330-
dispatchQueueWrapper:[self dispatchQueueWrapper]]);
324+
[[SentryUIViewControllerPerformanceTracker alloc] init]);
331325
# else
332326
SENTRY_LOG_DEBUG(@"SentryDependencyContainer.uiViewControllerPerformanceTracker only works "
333327
@"with UIKit enabled. Ensure you're "

Sources/Sentry/SentryPerformanceTrackingIntegration.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ - (BOOL)installWithOptions:(SentryOptions *)options
4343
binaryImageCache:[SentryDependencyContainer.sharedInstance binaryImageCache]];
4444

4545
[self.swizzling start];
46-
id<SentryUIViewControllerPerformanceTracker> performanceTracker =
46+
SentryUIViewControllerPerformanceTracker *performanceTracker =
4747
[SentryDependencyContainer.sharedInstance uiViewControllerPerformanceTracker];
4848
performanceTracker.alwaysWaitForFullDisplay = options.enableTimeToFullDisplayTracing;
4949

Sources/Sentry/SentryUIViewControllerSwizzling.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ - (void)start
110110
}
111111

112112
[self swizzleUIViewController];
113-
id<SentryUIViewControllerPerformanceTracker> performanceTracker =
113+
SentryUIViewControllerPerformanceTracker *performanceTracker =
114114
[SentryDependencyContainer.sharedInstance uiViewControllerPerformanceTracker];
115115
performanceTracker.inAppLogic = self.inAppLogic;
116116
}

Sources/Sentry/include/HybridPublic/SentryDependencyContainer.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@
4444
@class SentryScreenshotSource;
4545
@class SentryViewHierarchyProvider;
4646
@class SentryWatchdogTerminationAttributesProcessor;
47+
@class SentryUIViewControllerPerformanceTracker;
4748

4849
@protocol SentryScopeObserver;
49-
@protocol SentryUIViewControllerPerformanceTracker;
5050
#endif // SENTRY_UIKIT_AVAILABLE
5151

5252
#if SENTRY_HAS_UIKIT
@@ -120,8 +120,8 @@ SENTRY_NO_INIT
120120
#if SENTRY_UIKIT_AVAILABLE
121121
@property (nonatomic, strong) SentryFramesTracker *framesTracker;
122122
@property (nonatomic, strong) SentryViewHierarchyProvider *viewHierarchyProvider;
123-
@property (nonatomic, strong) id<SentryUIViewControllerPerformanceTracker>
124-
uiViewControllerPerformanceTracker;
123+
@property (nonatomic, strong)
124+
SentryUIViewControllerPerformanceTracker *uiViewControllerPerformanceTracker;
125125
#endif // SENTRY_UIKIT_AVAILABLE
126126

127127
#if SENTRY_TARGET_REPLAY_SUPPORTED

Sources/Sentry/include/SentryDefaultUIViewControllerPerformanceTracker.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,13 @@
99
@class SentryPerformanceTracker;
1010
@class SentryDispatchQueueWrapper;
1111

12-
@protocol SentryInitialDisplayReporting;
13-
1412
NS_ASSUME_NONNULL_BEGIN
1513

1614
@interface SentryObjCSwiftUISpanHelper : NSObject
1715

1816
@property (nonatomic, readonly) BOOL hasSpan;
1917

20-
@property (nonatomic, strong, readonly, nullable) id<SentryInitialDisplayReporting>
21-
initialDisplayReporting;
18+
- (void)reportInitialDisplay;
2219

2320
@end
2421

@@ -28,14 +25,11 @@ NS_ASSUME_NONNULL_BEGIN
2825
*/
2926
@interface SentryDefaultUIViewControllerPerformanceTracker : NSObject
3027

31-
@property (nonatomic, strong) SentryInAppLogic *inAppLogic;
32-
3328
@property (nonatomic) BOOL alwaysWaitForFullDisplay;
3429

3530
SENTRY_NO_INIT
3631

37-
- (instancetype)initWithTracker:(SentryPerformanceTracker *)tracker
38-
dispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper;
32+
- (instancetype)initWithTracker:(SentryPerformanceTracker *)tracker;
3933

4034
/**
4135
* Measures @c controller's @c loadView method.
@@ -46,6 +40,7 @@ SENTRY_NO_INIT
4640
* @c loadView method.
4741
*/
4842
- (void)viewControllerLoadView:(UIViewController *)controller
43+
isInApp:(BOOL (^)(Class))isInApp
4944
callbackToOrigin:(void (^)(void))callback;
5045

5146
/**
@@ -106,6 +101,10 @@ SENTRY_NO_INIT
106101

107102
- (void)reportFullyDisplayed;
108103

104+
- (SentryObjCSwiftUISpanHelper *)startTimeToDisplayTrackerForScreen:(NSString *)screenName
105+
waitForFullDisplay:(BOOL)waitforFullDisplay
106+
transactionId:(SentrySpanId *)transactionId;
107+
109108
+ (SentryObjCSwiftUISpanHelper *)startTimeToDisplayTrackerForScreen:(NSString *)screenName
110109
waitForFullDisplay:(BOOL)waitforFullDisplay
111110
transactionId:(SentrySpanId *)transactionId;

Sources/Sentry/include/SentryPrivate.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#import "SentryCrashMonitor_System.h"
3232
#import "SentryDateUtils.h"
3333
#import "SentryDefaultThreadInspector.h"
34+
#import "SentryDefaultUIViewControllerPerformanceTracker.h"
3435
#import "SentryDelayedFramesTracker.h"
3536
#import "SentryDependencyContainerSwiftHelper.h"
3637
#import "SentryDeviceContextKeys.h"
@@ -43,6 +44,7 @@
4344
#import "SentryMsgPackSerializer.h"
4445
#import "SentryNSDictionarySanitize.h"
4546
#import "SentryOptions+Private.h"
47+
#import "SentryPerformanceTracker.h"
4648
#import "SentryProfiler+Private.h"
4749
#import "SentrySDKInternal.h"
4850
#import "SentryScope+PrivateSwift.h"
Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#if (os(iOS) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT
22

3+
@_implementationOnly import _SentryPrivate
34
import UIKit
45

56
@_spi(Private) @objc public protocol SentryInitialDisplayReporting {
@@ -8,40 +9,80 @@ import UIKit
89

910
@_spi(Private) @objc public class SentrySwiftUISpanHelper: NSObject {
1011
@objc public let hasSpan: Bool
11-
@objc public let initialDisplayReporting: SentryInitialDisplayReporting?
1212

13-
@objc public init(hasSpan: Bool, initialDisplayReporting: SentryInitialDisplayReporting?) {
13+
@objc public func reportInitialDisplay() {
14+
initialDisplayReporting()
15+
}
16+
private let initialDisplayReporting: () -> Void
17+
18+
@objc public init(hasSpan: Bool, initialDisplayReporting: @escaping () -> Void) {
1419
self.hasSpan = hasSpan
1520
self.initialDisplayReporting = initialDisplayReporting
1621
}
1722
}
1823

19-
@_spi(Private) @objc public protocol SentryUIViewControllerPerformanceTracker {
24+
@_spi(Private) @objc public final class SentryUIViewControllerPerformanceTracker: NSObject {
2025

21-
var inAppLogic: SentryInAppLogic { get set }
26+
@objc private let helper: SentryDefaultUIViewControllerPerformanceTracker
2227

23-
var alwaysWaitForFullDisplay: Bool { get set }
28+
@objc public override init() {
29+
let options = SentrySDKInternal.options
30+
inAppLogic = SentryInAppLogic(inAppIncludes: options?.inAppIncludes ?? [], inAppExcludes: options?.inAppExcludes ?? [])
31+
helper = SentryDefaultUIViewControllerPerformanceTracker(tracker: SentryPerformanceTracker.shared)
32+
}
2433

25-
func viewControllerLoadView(_ controller: UIViewController, callbackToOrigin callback: @escaping () -> Void)
34+
@objc public var inAppLogic: SentryInAppLogic
2635

27-
func viewControllerViewDidLoad(_ controller: UIViewController, callbackToOrigin callback: @escaping () -> Void)
36+
@objc public var alwaysWaitForFullDisplay: Bool { get {
37+
helper.alwaysWaitForFullDisplay
38+
} set {
39+
helper.alwaysWaitForFullDisplay = newValue
40+
} }
2841

29-
func viewControllerViewWillAppear(_ controller: UIViewController, callbackToOrigin callback: @escaping () -> Void)
42+
@objc public func viewControllerLoadView(_ controller: UIViewController, callbackToOrigin callback: @escaping () -> Void) {
43+
let inAppLogic = self.inAppLogic
44+
helper.viewControllerLoadView(controller, isInApp: { c in
45+
inAppLogic.isClassInApp(c)
46+
}, callbackToOrigin: callback)
47+
}
3048

31-
func viewControllerViewWillDisappear(_ controller: UIViewController, callbackToOrigin callback: @escaping () -> Void)
49+
@objc public func viewControllerViewDidLoad(_ controller: UIViewController, callbackToOrigin callback: @escaping () -> Void) {
50+
helper.viewControllerViewDidLoad(controller, callbackToOrigin: callback)
51+
}
52+
53+
@objc public func viewControllerViewWillAppear(_ controller: UIViewController, callbackToOrigin callback: @escaping () -> Void) {
54+
helper.viewControllerViewWillAppear(controller, callbackToOrigin: callback)
55+
}
56+
57+
@objc public func viewControllerViewWillDisappear(_ controller: UIViewController, callbackToOrigin callback: @escaping () -> Void) {
58+
helper.viewControllerViewWillDisappear(controller, callbackToOrigin: callback)
59+
}
3260

33-
func viewControllerViewDidAppear(_ controller: UIViewController, callbackToOrigin callback: @escaping () -> Void)
61+
@objc public func viewControllerViewDidAppear(_ controller: UIViewController, callbackToOrigin callback: @escaping () -> Void) {
62+
helper.viewControllerViewDidAppear(controller, callbackToOrigin: callback)
63+
}
3464

35-
func viewControllerViewWillLayoutSubViews(_ controller: UIViewController, callbackToOrigin callback: @escaping () -> Void)
65+
@objc public func viewControllerViewWillLayoutSubViews(_ controller: UIViewController, callbackToOrigin callback: @escaping () -> Void) {
66+
helper.viewControllerViewWillLayoutSubViews(controller, callbackToOrigin: callback)
67+
}
3668

37-
func viewControllerViewDidLayoutSubViews(_ controller: UIViewController, callbackToOrigin callback: @escaping () -> Void)
69+
@objc public func viewControllerViewDidLayoutSubViews(_ controller: UIViewController, callbackToOrigin callback: @escaping () -> Void) {
70+
helper.viewControllerViewDidLayoutSubViews(controller, callbackToOrigin: callback)
71+
}
3872

39-
func reportFullyDisplayed()
73+
@objc public func reportFullyDisplayed() {
74+
helper.reportFullyDisplayed()
75+
}
4076

41-
func startTimeToDisplayTracker(
77+
@objc public func startTimeToDisplayTracker(
4278
forScreen screenName: String,
4379
waitForFullDisplay: Bool,
44-
transactionId: SpanId) -> SentrySwiftUISpanHelper
80+
transactionId: SpanId) -> SentrySwiftUISpanHelper {
81+
let objcType = helper.startTimeToDisplay(forScreen: screenName, waitForFullDisplay: waitForFullDisplay, transactionId: transactionId)
82+
return SentrySwiftUISpanHelper(hasSpan: objcType.hasSpan) {
83+
objcType.reportInitialDisplay()
84+
}
85+
}
4586
}
4687

4788
#endif

Tests/SentryTests/Integrations/Performance/UIViewController/SentryUIViewControllerPerformanceTrackerTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -411,17 +411,17 @@ class SentryUIViewControllerPerformanceTrackerTests: XCTestCase {
411411
//Left empty on purpose
412412
}
413413

414-
let ttdTracker = Dynamic(sut).currentTTDTracker.asObject as? SentryTimeToDisplayTracker
414+
let ttdTracker = Dynamic(Dynamic(sut).helper).currentTTDTracker.asObject as? SentryTimeToDisplayTracker
415415
XCTAssertNotNil(ttdTracker)
416416

417417
sut.viewControllerLoadView(viewController2) {
418418
//Left empty on purpose
419419
}
420420

421-
let trackers = try XCTUnwrap(Dynamic(sut).ttdTrackers.asObject as? SentryWeakMap<TestViewController, AnyObject>)
421+
let trackers = try XCTUnwrap(Dynamic(Dynamic(sut).helper).ttdTrackers.asObject as? SentryWeakMap<TestViewController, AnyObject>)
422422
let secondTTDTracker = trackers.object(forKey: viewController2)
423423

424-
XCTAssertEqual(ttdTracker, Dynamic(sut).currentTTDTracker.asObject)
424+
XCTAssertEqual(ttdTracker, Dynamic(Dynamic(sut).helper).currentTTDTracker.asObject)
425425
XCTAssertNil(secondTTDTracker)
426426
}
427427

Tests/SentryTests/SentryHubTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1223,7 +1223,7 @@ class SentryHubTests: XCTestCase {
12231223
let testTTDTracker = TestTimeToDisplayTracker(waitForFullDisplay: true)
12241224

12251225
let performanceTracker = Dynamic(SentryDependencyContainer.sharedInstance().uiViewControllerPerformanceTracker)
1226-
performanceTracker.currentTTDTracker = testTTDTracker
1226+
Dynamic(performanceTracker.helper).currentTTDTracker = testTTDTracker
12271227

12281228
// -- Act --
12291229
sut.reportFullyDisplayed()

0 commit comments

Comments
 (0)