Skip to content

Commit 79930f1

Browse files
feat(ttd): TimeToInitialDisplay and TimeToFullDisplay start the time to display spans on mount (#4020)
1 parent 53f7698 commit 79930f1

File tree

3 files changed

+62
-1
lines changed

3 files changed

+62
-1
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
### Features
6+
7+
- `TimeToInitialDisplay` and `TimeToFullDisplay` start the time to display spans on mount ([#4020](https://github.com/getsentry/sentry-react-native/pull/4020))
8+
59
### Fixed
610

711
- fix(ttid): End and measure TTID regardless current active span ([#4019](https://github.com/getsentry/sentry-react-native/pull/4019))

src/js/tracing/timetodisplay.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export function TimeToInitialDisplay(props: TimeToDisplayProps): React.ReactElem
3636
const activeSpan = getActiveSpan();
3737
if (activeSpan) {
3838
manualInitialDisplaySpans.set(activeSpan, true);
39+
startTimeToInitialDisplaySpan();
3940
}
4041

4142
return <TimeToDisplay initialDisplay={props.record}>{props.children}</TimeToDisplay>;
@@ -49,6 +50,7 @@ export function TimeToInitialDisplay(props: TimeToDisplayProps): React.ReactElem
4950
* <TimeToInitialDisplay record />
5051
*/
5152
export function TimeToFullDisplay(props: TimeToDisplayProps): React.ReactElement {
53+
startTimeToFullDisplaySpan();
5254
return <TimeToDisplay fullDisplay={props.record}>{props.children}</TimeToDisplay>;
5355
}
5456

test/tracing/timetodisplay.test.tsx

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as mockedtimetodisplaynative from './mockedtimetodisplaynative';
22
jest.mock('../../src/js/tracing/timetodisplaynative', () => mockedtimetodisplaynative);
33

44
import type { Span as SpanClass} from '@sentry/core';
5-
import { getCurrentScope, getGlobalScope, getIsolationScope, setCurrentClient, spanToJSON, startSpanManual} from '@sentry/core';
5+
import { getActiveSpan, getCurrentScope, getGlobalScope, getIsolationScope, setCurrentClient, spanToJSON, startSpanManual} from '@sentry/core';
66
import type { Event, Measurements, Span, SpanJSON} from '@sentry/types';
77
import React from "react";
88
import TestRenderer from 'react-test-renderer';
@@ -92,6 +92,61 @@ describe('TimeToDisplay', () => {
9292
expect(spanToJSON(testSpan!).start_timestamp).toEqual(spanToJSON(activeSpan!).start_timestamp);
9393
});
9494

95+
test('creates initial display span on first component render', async () => {
96+
const [testSpan, activeSpan] = startSpanManual(
97+
{
98+
name: 'Root Manual Span',
99+
startTime: secondAgoTimestampMs(),
100+
},
101+
(activeSpan: Span | undefined) => {
102+
const renderer = TestRenderer.create(<TimeToInitialDisplay record={false} />);
103+
const testSpan = (getActiveSpan() as SpanClass).spanRecorder?.spans.find((span) => spanToJSON(span).op === 'ui.load.initial_display');
104+
105+
renderer.update(<TimeToInitialDisplay record={true} />);
106+
emitNativeInitialDisplayEvent();
107+
108+
activeSpan?.end();
109+
return [testSpan, activeSpan];
110+
},
111+
);
112+
113+
await jest.runOnlyPendingTimersAsync();
114+
await client.flush();
115+
116+
expectInitialDisplayMeasurementOnSpan(client.event!);
117+
expectFinishedInitialDisplaySpan(testSpan, activeSpan);
118+
expect(spanToJSON(testSpan!).start_timestamp).toEqual(spanToJSON(activeSpan!).start_timestamp);
119+
});
120+
121+
test('creates full display span on first component render', async () => {
122+
const [testSpan, activeSpan] = startSpanManual(
123+
{
124+
name: 'Root Manual Span',
125+
startTime: secondAgoTimestampMs(),
126+
},
127+
(activeSpan: Span | undefined) => {
128+
TestRenderer.create(<TimeToInitialDisplay record={true} />);
129+
emitNativeInitialDisplayEvent();
130+
131+
const renderer = TestRenderer.create(<TimeToFullDisplay record={false} />);
132+
const testSpan = (getActiveSpan() as SpanClass).spanRecorder?.spans.find((span) => spanToJSON(span).op === 'ui.load.full_display');
133+
134+
renderer.update(<TimeToFullDisplay record={true} />);
135+
emitNativeFullDisplayEvent();
136+
137+
activeSpan?.end();
138+
return [testSpan, activeSpan];
139+
},
140+
);
141+
142+
await jest.runOnlyPendingTimersAsync();
143+
await client.flush();
144+
145+
expectFullDisplayMeasurementOnSpan(client.event!);
146+
expectFinishedFullDisplaySpan(testSpan, activeSpan);
147+
expect(spanToJSON(testSpan!).start_timestamp).toEqual(spanToJSON(activeSpan!).start_timestamp);
148+
});
149+
95150
test('does not create full display when initial display is missing', async () => {
96151
const [activeSpan] = startSpanManual(
97152
{

0 commit comments

Comments
 (0)