Skip to content

Commit e4df67c

Browse files
authored
Merge 8c4a9d7 into a0b0298
2 parents a0b0298 + 8c4a9d7 commit e4df67c

File tree

8 files changed

+109
-12
lines changed

8 files changed

+109
-12
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66
> make sure you follow our [migration guide](https://docs.sentry.io/platforms/react-native/migration/) first.
77
<!-- prettier-ignore-end -->
88
9+
## Unreleased
10+
11+
### Features
12+
13+
- Add thread information to spans ([#4579](https://github.com/getsentry/sentry-react-native/pull/4579))
14+
915
## 6.9.0
1016

1117
### Features
@@ -16,7 +22,7 @@
1622

1723
```js
1824
import Sentry from "@sentry/react-native";
19-
25+
2026
Sentry.showFeedbackWidget();
2127

2228
Sentry.wrap(RootComponent);

packages/core/src/js/tracing/integrations/appStart.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* eslint-disable complexity */
1+
/* eslint-disable complexity, max-lines */
22
import type { Client, Event, Integration, SpanJSON, TransactionEvent } from '@sentry/core';
33
import {
44
getCapturedScopesOnSpan,
@@ -26,6 +26,7 @@ import {
2626
} from '../ops';
2727
import { SPAN_ORIGIN_AUTO_APP_START, SPAN_ORIGIN_MANUAL_APP_START } from '../origin';
2828
import { SEMANTIC_ATTRIBUTE_SENTRY_OP } from '../semanticAttributes';
29+
import { setMainThreadInfo } from '../span';
2930
import { createChildSpanJSON, createSpanJSON, getBundleStartTimestampMs } from '../utils';
3031

3132
const INTEGRATION_NAME = 'AppStart';
@@ -384,15 +385,17 @@ function createJSExecutionStartSpan(
384385
function convertNativeSpansToSpanJSON(parentSpan: SpanJSON, nativeSpans: NativeAppStartResponse['spans']): SpanJSON[] {
385386
return nativeSpans.map(span => {
386387
if (span.description === 'UIKit init') {
387-
return createUIKitSpan(parentSpan, span);
388+
return setMainThreadInfo(createUIKitSpan(parentSpan, span));
388389
}
389390

390-
return createChildSpanJSON(parentSpan, {
391-
description: span.description,
392-
start_timestamp: span.start_timestamp_ms / 1000,
393-
timestamp: span.end_timestamp_ms / 1000,
394-
origin: SPAN_ORIGIN_AUTO_APP_START,
395-
});
391+
return setMainThreadInfo(
392+
createChildSpanJSON(parentSpan, {
393+
description: span.description,
394+
start_timestamp: span.start_timestamp_ms / 1000,
395+
timestamp: span.end_timestamp_ms / 1000,
396+
origin: SPAN_ORIGIN_AUTO_APP_START,
397+
}),
398+
);
396399
});
397400
}
398401

packages/core/src/js/tracing/reactnativetracing.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { getClient } from '@sentry/core';
55

66
import { isWeb } from '../utils/environment';
77
import { getDevServer } from './../integrations/debugsymbolicatorutils';
8-
import { addDefaultOpForSpanFrom, defaultIdleOptions } from './span';
8+
import { addDefaultOpForSpanFrom, addThreadInfoToSpan, defaultIdleOptions } from './span';
99

1010
export const INTEGRATION_NAME = 'ReactNativeTracing';
1111

@@ -119,6 +119,7 @@ export const reactNativeTracingIntegration = (
119119

120120
const setup = (client: Client): void => {
121121
addDefaultOpForSpanFrom(client);
122+
addThreadInfoToSpan(client);
122123

123124
instrumentOutgoingRequests(client, {
124125
traceFetch: finalOptions.traceFetch,

packages/core/src/js/tracing/span.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Client, Scope, Span, StartSpanOptions } from '@sentry/core';
1+
import type { Client, Scope, Span, SpanJSON, StartSpanOptions } from '@sentry/core';
22
import {
33
generatePropagationContext,
44
getActiveSpan,
@@ -154,3 +154,33 @@ export function addDefaultOpForSpanFrom(client: Client): void {
154154
}
155155
});
156156
}
157+
158+
export const SPAN_THREAD_ID = 'thread.id';
159+
export const SPAN_THREAD_ID_MAIN = 1;
160+
export const SPAN_THREAD_ID_JAVASCRIPT = 2;
161+
export const SPAN_THREAD_NAME = 'thread.name';
162+
export const SPAN_THREAD_NAME_MAIN = 'main';
163+
export const SPAN_THREAD_NAME_JAVASCRIPT = 'javascript';
164+
165+
/**
166+
* Adds Javascript thread info to spans.
167+
* Ref: https://reactnative.dev/architecture/threading-model
168+
*/
169+
export function addThreadInfoToSpan(client: Client): void {
170+
client.on('spanStart', (span: Span) => {
171+
if (!spanToJSON(span).data?.[SPAN_THREAD_ID]) {
172+
span.setAttribute(SPAN_THREAD_ID, SPAN_THREAD_ID_JAVASCRIPT);
173+
span.setAttribute(SPAN_THREAD_NAME, SPAN_THREAD_NAME_JAVASCRIPT);
174+
}
175+
});
176+
}
177+
178+
/**
179+
* Sets the Main thread info to the span.
180+
*/
181+
export function setMainThreadInfo(spanJSON: SpanJSON): SpanJSON {
182+
spanJSON.data = spanJSON.data || {};
183+
spanJSON.data[SPAN_THREAD_ID] = SPAN_THREAD_ID_MAIN;
184+
spanJSON.data[SPAN_THREAD_NAME] = SPAN_THREAD_NAME_MAIN;
185+
return spanJSON;
186+
}

packages/core/test/tracing/integrations/appStart.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ import {
2727
setRootComponentCreationTimestampMs,
2828
} from '../../../src/js/tracing/integrations/appStart';
2929
import { SPAN_ORIGIN_AUTO_APP_START, SPAN_ORIGIN_MANUAL_APP_START } from '../../../src/js/tracing/origin';
30+
import {
31+
SPAN_THREAD_ID,
32+
SPAN_THREAD_ID_MAIN,
33+
SPAN_THREAD_NAME,
34+
SPAN_THREAD_NAME_MAIN,
35+
} from '../../../src/js/tracing/span';
3036
import { getTimeOriginMilliseconds } from '../../../src/js/tracing/utils';
3137
import { RN_GLOBAL_OBJ } from '../../../src/js/utils/worldwide';
3238
import { NATIVE } from '../../../src/js/wrapper';
@@ -252,6 +258,8 @@ describe('App Start Integration', () => {
252258
data: {
253259
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: appStartRootSpan!.op,
254260
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: SPAN_ORIGIN_AUTO_APP_START,
261+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_MAIN,
262+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_MAIN,
255263
},
256264
}),
257265
);
@@ -612,6 +620,8 @@ describe('App Start Integration', () => {
612620
data: {
613621
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: appStartRootSpan!.op,
614622
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: SPAN_ORIGIN_AUTO_APP_START,
623+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_MAIN,
624+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_MAIN,
615625
},
616626
}),
617627
);

packages/core/test/tracing/reactnativenavigation.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ import {
3232
SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE,
3333
SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
3434
} from '../../src/js/tracing/semanticAttributes';
35+
import {
36+
SPAN_THREAD_ID,
37+
SPAN_THREAD_ID_JAVASCRIPT,
38+
SPAN_THREAD_NAME,
39+
SPAN_THREAD_NAME_JAVASCRIPT,
40+
} from '../../src/js/tracing/span';
3541
import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
3642

3743
interface MockEventsRegistry extends EventsRegistry {
@@ -87,6 +93,8 @@ describe('React Native Navigation Instrumentation', () => {
8793
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
8894
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
8995
[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]: 'idleTimeout',
96+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
97+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
9098
},
9199
}),
92100
}),
@@ -131,6 +139,8 @@ describe('React Native Navigation Instrumentation', () => {
131139
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
132140
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
133141
[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]: 'idleTimeout',
142+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
143+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
134144
},
135145
}),
136146
}),
@@ -206,6 +216,8 @@ describe('React Native Navigation Instrumentation', () => {
206216
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
207217
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
208218
[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]: 'idleTimeout',
219+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
220+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
209221
},
210222
}),
211223
}),
@@ -294,6 +306,8 @@ describe('React Native Navigation Instrumentation', () => {
294306
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
295307
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
296308
[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]: 'idleTimeout',
309+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
310+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
297311
},
298312
}),
299313
}),
@@ -342,6 +356,8 @@ describe('React Native Navigation Instrumentation', () => {
342356
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
343357
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
344358
[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]: 'idleTimeout',
359+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
360+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
345361
},
346362
}),
347363
}),

packages/core/test/tracing/reactnavigation.test.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@ import {
2020
SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE,
2121
SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
2222
} from '../../src/js/tracing/semanticAttributes';
23-
import { DEFAULT_NAVIGATION_SPAN_NAME } from '../../src/js/tracing/span';
23+
import {
24+
DEFAULT_NAVIGATION_SPAN_NAME,
25+
SPAN_THREAD_ID,
26+
SPAN_THREAD_ID_JAVASCRIPT,
27+
SPAN_THREAD_NAME,
28+
SPAN_THREAD_NAME_JAVASCRIPT,
29+
} from '../../src/js/tracing/span';
2430
import { RN_GLOBAL_OBJ } from '../../src/js/utils/worldwide';
2531
import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
2632
import { NATIVE } from '../mockWrapper';
@@ -83,6 +89,8 @@ describe('ReactNavigationInstrumentation', () => {
8389
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
8490
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
8591
[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]: 'idleTimeout',
92+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
93+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
8694
},
8795
}),
8896
}),
@@ -192,6 +200,8 @@ describe('ReactNavigationInstrumentation', () => {
192200
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
193201
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
194202
[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]: 'idleTimeout',
203+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
204+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
195205
},
196206
}),
197207
}),
@@ -229,6 +239,8 @@ describe('ReactNavigationInstrumentation', () => {
229239
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
230240
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
231241
[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]: 'idleTimeout',
242+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
243+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
232244
},
233245
}),
234246
}),
@@ -268,6 +280,8 @@ describe('ReactNavigationInstrumentation', () => {
268280
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
269281
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
270282
[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]: 'idleTimeout',
283+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
284+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
271285
},
272286
}),
273287
}),

packages/core/test/tracing/reactnavigation.ttid.test.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { startSpanManual } from '../../src/js';
1616
import { TimeToFullDisplay, TimeToInitialDisplay } from '../../src/js/tracing';
1717
import { _setAppStartEndTimestampMs } from '../../src/js/tracing/integrations/appStart';
1818
import { SPAN_ORIGIN_AUTO_NAVIGATION_REACT_NAVIGATION, SPAN_ORIGIN_AUTO_UI_TIME_TO_DISPLAY, SPAN_ORIGIN_MANUAL_UI_TIME_TO_DISPLAY } from '../../src/js/tracing/origin';
19+
import { SPAN_THREAD_ID, SPAN_THREAD_ID_JAVASCRIPT, SPAN_THREAD_NAME, SPAN_THREAD_NAME_JAVASCRIPT } from '../../src/js/tracing/span';
1920
import { isHermesEnabled, notWeb } from '../../src/js/utils/environment';
2021
import { createSentryFallbackEventEmitter } from '../../src/js/utils/sentryeventemitterfallback';
2122
import { RN_GLOBAL_OBJ } from '../../src/js/utils/worldwide';
@@ -80,6 +81,8 @@ describe('React Navigation - TTID', () => {
8081
data: {
8182
'sentry.op': 'ui.load.initial_display',
8283
'sentry.origin': SPAN_ORIGIN_AUTO_UI_TIME_TO_DISPLAY,
84+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
85+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
8386
},
8487
description: 'New Screen initial display',
8588
op: 'ui.load.initial_display',
@@ -110,6 +113,8 @@ describe('React Navigation - TTID', () => {
110113
data: {
111114
'sentry.op': 'ui.load.initial_display',
112115
'sentry.origin': SPAN_ORIGIN_AUTO_UI_TIME_TO_DISPLAY,
116+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
117+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
113118
},
114119
description: 'New Screen initial display',
115120
op: 'ui.load.initial_display',
@@ -146,6 +151,8 @@ describe('React Navigation - TTID', () => {
146151
data: {
147152
'sentry.op': 'ui.load.initial_display',
148153
'sentry.origin': SPAN_ORIGIN_AUTO_UI_TIME_TO_DISPLAY,
154+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
155+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
149156
},
150157
description: 'New Screen initial display',
151158
op: 'ui.load.initial_display',
@@ -203,6 +210,8 @@ describe('React Navigation - TTID', () => {
203210
'sentry.op': 'navigation.processing',
204211
'sentry.origin': SPAN_ORIGIN_AUTO_NAVIGATION_REACT_NAVIGATION,
205212
'sentry.source': 'custom',
213+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
214+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
206215
},
207216
description: 'Navigation dispatch to screen New Screen mounted',
208217
op: 'navigation.processing',
@@ -231,6 +240,8 @@ describe('React Navigation - TTID', () => {
231240
'sentry.op': 'navigation.processing',
232241
'sentry.origin': SPAN_ORIGIN_AUTO_NAVIGATION_REACT_NAVIGATION,
233242
'sentry.source': 'custom',
243+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
244+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
234245
},
235246
description: 'Navigation dispatch to screen Initial Screen mounted',
236247
op: 'navigation.processing',
@@ -261,6 +272,8 @@ describe('React Navigation - TTID', () => {
261272
data: {
262273
'sentry.op': 'ui.load.initial_display',
263274
'sentry.origin': SPAN_ORIGIN_AUTO_UI_TIME_TO_DISPLAY,
275+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
276+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
264277
},
265278
description: 'Initial Screen initial display',
266279
op: 'ui.load.initial_display',
@@ -295,6 +308,8 @@ describe('React Navigation - TTID', () => {
295308
data: {
296309
'sentry.op': 'ui.load.full_display',
297310
'sentry.origin': SPAN_ORIGIN_MANUAL_UI_TIME_TO_DISPLAY,
311+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
312+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
298313
},
299314
description: 'Time To Full Display',
300315
op: 'ui.load.full_display',
@@ -371,6 +386,8 @@ describe('React Navigation - TTID', () => {
371386
data: {
372387
'sentry.op': 'ui.load.initial_display',
373388
'sentry.origin': SPAN_ORIGIN_AUTO_UI_TIME_TO_DISPLAY,
389+
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
390+
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
374391
},
375392
description: 'New Screen initial display',
376393
op: 'ui.load.initial_display',

0 commit comments

Comments
 (0)