Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Adds span thread info #4579

Merged
merged 11 commits into from
Feb 25, 2025
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

```js
import Sentry from "@sentry/react-native";

Sentry.showFeedbackWidget();

Sentry.wrap(RootComponent);
Expand All @@ -41,6 +41,8 @@

To learn more about the available configuration options visit [the documentation](https://docs.sentry.io/platforms/react-native/user-feedback/configuration).

- Add thread information to spans ([#4579](https://github.com/getsentry/sentry-react-native/pull/4579))

## 6.8.0

### Features
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/js/tracing/reactnativetracing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { getClient } from '@sentry/core';

import { isWeb } from '../utils/environment';
import { getDevServer } from './../integrations/debugsymbolicatorutils';
import { addDefaultOpForSpanFrom, defaultIdleOptions } from './span';
import { addDefaultOpForSpanFrom, addThreadInfoToSpan, defaultIdleOptions } from './span';

export const INTEGRATION_NAME = 'ReactNativeTracing';

Expand Down Expand Up @@ -119,6 +119,7 @@ export const reactNativeTracingIntegration = (

const setup = (client: Client): void => {
addDefaultOpForSpanFrom(client);
addThreadInfoToSpan(client);

instrumentOutgoingRequests(client, {
traceFetch: finalOptions.traceFetch,
Expand Down
27 changes: 27 additions & 0 deletions packages/core/src/js/tracing/span.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,30 @@ export function addDefaultOpForSpanFrom(client: Client): void {
}
});
}

export const SPAN_THREAD_ID = 'thread.id';
export const SPAN_THREAD_ID_MAIN = 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depending on the scenario and where the value is read from sentry-cocoa sets MAIN_ID as 0 or 259.

I don't know the situation on Android, but I think we should leave the IDs for now until we establish how to read them so they map correctly to what the native SDKs are reporting.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense @krystofwoldrich 👍
Removed the thread id with 9163202 and I'll investigate how to get this information from the native SDKs separately

export const SPAN_THREAD_ID_JAVASCRIPT = 2;
export const SPAN_THREAD_NAME = 'thread.name';
export const SPAN_THREAD_NAME_MAIN = 'main';
export const SPAN_THREAD_NAME_JAVASCRIPT = 'javascript';

const UI_THREAD_PREFIX = 'ui.';

/**
* Adds thread info to spans.
* Ref: https://reactnative.dev/architecture/threading-model
*/
export function addThreadInfoToSpan(client: Client): void {
client.on('spanStart', (span: Span) => {
if (!spanToJSON(span).data?.[SPAN_THREAD_ID]) {
if (spanToJSON(span).op?.startsWith(UI_THREAD_PREFIX)) {
span.setAttribute(SPAN_THREAD_ID, SPAN_THREAD_ID_MAIN);
span.setAttribute(SPAN_THREAD_NAME, SPAN_THREAD_NAME_MAIN);
} else {
span.setAttribute(SPAN_THREAD_ID, SPAN_THREAD_ID_JAVASCRIPT);
span.setAttribute(SPAN_THREAD_NAME, SPAN_THREAD_NAME_JAVASCRIPT);
}
}
});
}
16 changes: 16 additions & 0 deletions packages/core/test/tracing/reactnativenavigation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ import {
SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE,
SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
} from '../../src/js/tracing/semanticAttributes';
import {
SPAN_THREAD_ID,
SPAN_THREAD_ID_JAVASCRIPT,
SPAN_THREAD_NAME,
SPAN_THREAD_NAME_JAVASCRIPT,
} from '../../src/js/tracing/span';
import { getDefaultTestClientOptions, TestClient } from '../mocks/client';

interface MockEventsRegistry extends EventsRegistry {
Expand Down Expand Up @@ -87,6 +93,8 @@ describe('React Native Navigation Instrumentation', () => {
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]: 'idleTimeout',
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
},
}),
}),
Expand Down Expand Up @@ -131,6 +139,8 @@ describe('React Native Navigation Instrumentation', () => {
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]: 'idleTimeout',
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
},
}),
}),
Expand Down Expand Up @@ -206,6 +216,8 @@ describe('React Native Navigation Instrumentation', () => {
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]: 'idleTimeout',
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
},
}),
}),
Expand Down Expand Up @@ -294,6 +306,8 @@ describe('React Native Navigation Instrumentation', () => {
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]: 'idleTimeout',
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
},
}),
}),
Expand Down Expand Up @@ -342,6 +356,8 @@ describe('React Native Navigation Instrumentation', () => {
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]: 'idleTimeout',
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
},
}),
}),
Expand Down
16 changes: 15 additions & 1 deletion packages/core/test/tracing/reactnavigation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ import {
SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE,
SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
} from '../../src/js/tracing/semanticAttributes';
import { DEFAULT_NAVIGATION_SPAN_NAME } from '../../src/js/tracing/span';
import {
DEFAULT_NAVIGATION_SPAN_NAME,
SPAN_THREAD_ID,
SPAN_THREAD_ID_JAVASCRIPT,
SPAN_THREAD_NAME,
SPAN_THREAD_NAME_JAVASCRIPT,
} from '../../src/js/tracing/span';
import { RN_GLOBAL_OBJ } from '../../src/js/utils/worldwide';
import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
import { NATIVE } from '../mockWrapper';
Expand Down Expand Up @@ -83,6 +89,8 @@ describe('ReactNavigationInstrumentation', () => {
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]: 'idleTimeout',
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
},
}),
}),
Expand Down Expand Up @@ -192,6 +200,8 @@ describe('ReactNavigationInstrumentation', () => {
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]: 'idleTimeout',
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
},
}),
}),
Expand Down Expand Up @@ -229,6 +239,8 @@ describe('ReactNavigationInstrumentation', () => {
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]: 'idleTimeout',
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
},
}),
}),
Expand Down Expand Up @@ -268,6 +280,8 @@ describe('ReactNavigationInstrumentation', () => {
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]: 'idleTimeout',
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
},
}),
}),
Expand Down
17 changes: 17 additions & 0 deletions packages/core/test/tracing/reactnavigation.ttid.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { startSpanManual } from '../../src/js';
import { TimeToFullDisplay, TimeToInitialDisplay } from '../../src/js/tracing';
import { _setAppStartEndTimestampMs } from '../../src/js/tracing/integrations/appStart';
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';
import { SPAN_THREAD_ID, SPAN_THREAD_ID_JAVASCRIPT, SPAN_THREAD_ID_MAIN, SPAN_THREAD_NAME, SPAN_THREAD_NAME_JAVASCRIPT,SPAN_THREAD_NAME_MAIN } from '../../src/js/tracing/span';
import { isHermesEnabled, notWeb } from '../../src/js/utils/environment';
import { createSentryFallbackEventEmitter } from '../../src/js/utils/sentryeventemitterfallback';
import { RN_GLOBAL_OBJ } from '../../src/js/utils/worldwide';
Expand Down Expand Up @@ -80,6 +81,8 @@ describe('React Navigation - TTID', () => {
data: {
'sentry.op': 'ui.load.initial_display',
'sentry.origin': SPAN_ORIGIN_AUTO_UI_TIME_TO_DISPLAY,
[SPAN_THREAD_ID]: SPAN_THREAD_ID_MAIN,
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_MAIN,
},
description: 'New Screen initial display',
op: 'ui.load.initial_display',
Expand Down Expand Up @@ -110,6 +113,8 @@ describe('React Navigation - TTID', () => {
data: {
'sentry.op': 'ui.load.initial_display',
'sentry.origin': SPAN_ORIGIN_AUTO_UI_TIME_TO_DISPLAY,
[SPAN_THREAD_ID]: SPAN_THREAD_ID_MAIN,
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_MAIN,
},
description: 'New Screen initial display',
op: 'ui.load.initial_display',
Expand Down Expand Up @@ -146,6 +151,8 @@ describe('React Navigation - TTID', () => {
data: {
'sentry.op': 'ui.load.initial_display',
'sentry.origin': SPAN_ORIGIN_AUTO_UI_TIME_TO_DISPLAY,
[SPAN_THREAD_ID]: SPAN_THREAD_ID_MAIN,
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_MAIN,
},
description: 'New Screen initial display',
op: 'ui.load.initial_display',
Expand Down Expand Up @@ -203,6 +210,8 @@ describe('React Navigation - TTID', () => {
'sentry.op': 'navigation.processing',
'sentry.origin': SPAN_ORIGIN_AUTO_NAVIGATION_REACT_NAVIGATION,
'sentry.source': 'custom',
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
},
description: 'Navigation dispatch to screen New Screen mounted',
op: 'navigation.processing',
Expand Down Expand Up @@ -231,6 +240,8 @@ describe('React Navigation - TTID', () => {
'sentry.op': 'navigation.processing',
'sentry.origin': SPAN_ORIGIN_AUTO_NAVIGATION_REACT_NAVIGATION,
'sentry.source': 'custom',
[SPAN_THREAD_ID]: SPAN_THREAD_ID_JAVASCRIPT,
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_JAVASCRIPT,
},
description: 'Navigation dispatch to screen Initial Screen mounted',
op: 'navigation.processing',
Expand Down Expand Up @@ -261,6 +272,8 @@ describe('React Navigation - TTID', () => {
data: {
'sentry.op': 'ui.load.initial_display',
'sentry.origin': SPAN_ORIGIN_AUTO_UI_TIME_TO_DISPLAY,
[SPAN_THREAD_ID]: SPAN_THREAD_ID_MAIN,
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_MAIN,
},
description: 'Initial Screen initial display',
op: 'ui.load.initial_display',
Expand Down Expand Up @@ -295,6 +308,8 @@ describe('React Navigation - TTID', () => {
data: {
'sentry.op': 'ui.load.full_display',
'sentry.origin': SPAN_ORIGIN_MANUAL_UI_TIME_TO_DISPLAY,
[SPAN_THREAD_ID]: SPAN_THREAD_ID_MAIN,
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_MAIN,
},
description: 'Time To Full Display',
op: 'ui.load.full_display',
Expand Down Expand Up @@ -371,6 +386,8 @@ describe('React Navigation - TTID', () => {
data: {
'sentry.op': 'ui.load.initial_display',
'sentry.origin': SPAN_ORIGIN_AUTO_UI_TIME_TO_DISPLAY,
[SPAN_THREAD_ID]: SPAN_THREAD_ID_MAIN,
[SPAN_THREAD_NAME]: SPAN_THREAD_NAME_MAIN,
},
description: 'New Screen initial display',
op: 'ui.load.initial_display',
Expand Down
Loading