Skip to content

Commit

Permalink
fix: Add TTID/TTFD spans when loadView skipped
Browse files Browse the repository at this point in the history
The SDK creates a transaction when only viewDidLoad gets called for a
UIViewController but doesn't create TTID/TTFD spans, leading to
transactions missing TTID/TTFD data. Now, the SDK also creates TTID/TTFD
spans when only viewDidLoad gets called and loadView gets skipped.

Fixes GH-4396
  • Loading branch information
philipphofmann committed Oct 8, 2024
1 parent 9cd19dd commit 7140e19
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

- Edge case for swizzleClassNameExclude (#4405): Skip creating transactions for UIViewControllers ignored for swizzling
via the option `swizzleClassNameExclude`.
- Add TTID/TTFD spans when loadView gets skipped (#4415)

## 8.38.0-beta.1

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ class SecondarySplitViewController: UIViewController {

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
SentrySDK.reportFullyDisplayed()

if let topvc = TopViewControllerInspector.shared {
topvc.bringToFront()
Expand Down
1 change: 1 addition & 0 deletions Sources/Sentry/SentryUIViewControllerPerformanceTracker.m
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ - (void)viewControllerViewDidLoad:(UIViewController *)controller
block:^{
SENTRY_LOG_DEBUG(@"Tracking viewDidLoad");
[self createTransaction:controller];
[self createTimeToDisplay:controller];
[self measurePerformance:@"viewDidLoad"
target:controller
callbackToOrigin:callbackToOrigin];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,6 @@ class SentryUIViewControllerPerformanceTrackerTests: XCTestCase {

sut.enableWaitForFullDisplay = true

//The first view controller creates a transaction
sut.viewControllerLoadView(firstController) {
tracer = self.getStack(tracker).first as? SentryTracer
}
Expand All @@ -594,13 +593,64 @@ class SentryUIViewControllerPerformanceTrackerTests: XCTestCase {

sut.enableWaitForFullDisplay = false

//The first view controller creates a transaction
sut.viewControllerLoadView(firstController) {
tracer = self.getStack(tracker).first as? SentryTracer
}

XCTAssertEqual(tracer?.children.count, 2)
}

func test_OnlyViewDidLoad_CreatesTTIDSpan() throws {
let sut = fixture.getSut()
let tracker = fixture.tracker

var tracer: SentryTracer!

sut.viewControllerViewDidLoad(TestViewController()) {
tracer = self.getStack(tracker).first as? SentryTracer
}

let children: [Span]? = Dynamic(tracer).children as [Span]?

XCTAssertEqual(children?.count, 2)

let firstChild = try XCTUnwrap(children?.first)
XCTAssertEqual("ui.load.initial_display", firstChild.operation)
XCTAssertEqual("TestViewController initial display", firstChild.spanDescription)
let secondChild = try XCTUnwrap(children?[1])
XCTAssertEqual("ui.load", secondChild.operation)
XCTAssertEqual("viewDidLoad", secondChild.spanDescription)
}

func test_OnlyLoadViewAndViewDidLoad_CreatesOneTTIDSpan() throws {
let sut = fixture.getSut()
let tracker = fixture.tracker
let controller = TestViewController()
var tracer: SentryTracer!

sut.viewControllerLoadView(controller) {
tracer = self.getStack(tracker).first as? SentryTracer
}

sut.viewControllerViewDidLoad(controller) {
// Empty on purpose
}

let children: [Span]? = Dynamic(tracer).children as [Span]?

XCTAssertEqual(children?.count, 3)

let child1 = try XCTUnwrap(children?.first)
XCTAssertEqual("ui.load.initial_display", child1.operation)

let child2 = try XCTUnwrap(children?[1])
XCTAssertEqual("ui.load", child2.operation)
XCTAssertEqual("loadView", child2.spanDescription)

let child3 = try XCTUnwrap(children?[2])
XCTAssertEqual("ui.load", child3.operation)
XCTAssertEqual("viewDidLoad", child3.spanDescription)
}

func test_captureAllAutomaticSpans() {
let sut = fixture.getSut()
Expand Down Expand Up @@ -643,12 +693,13 @@ class SentryUIViewControllerPerformanceTrackerTests: XCTestCase {

let children: [Span]? = Dynamic(tracer).children as [Span]?

//First Controller viewDidLoad
//Second Controller root span
//Second Controller viewDidLoad
//Third Controller root span
//Third Controller viewDidLoad
XCTAssertEqual(children?.count, 5)
// First Controller initial_display
// First Controller viewDidLoad
// Second Controller root span
// Second Controller viewDidLoad
// Third Controller root span
// Third Controller viewDidLoad
XCTAssertEqual(children?.count, 6)
}

private func assertSpanDuration(span: Span?, expectedDuration: TimeInterval) throws {
Expand Down

0 comments on commit 7140e19

Please sign in to comment.