@sentry/react-native
Version:
Official Sentry SDK for react-native
106 lines • 4.55 kB
JavaScript
import { generatePropagationContext, getActiveSpan, getClient, getCurrentScope, logger, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SentryNonRecordingSpan, SPAN_STATUS_ERROR, spanToJSON, startIdleSpan as coreStartIdleSpan, } from '@sentry/core';
import { isRootSpan } from '../utils/span';
import { adjustTransactionDuration, cancelInBackground } from './onSpanEndUtils';
import { SPAN_ORIGIN_AUTO_INTERACTION, SPAN_ORIGIN_AUTO_NAVIGATION_CUSTOM, SPAN_ORIGIN_MANUAL_INTERACTION, } from './origin';
export const DEFAULT_NAVIGATION_SPAN_NAME = 'Route Change';
export const defaultIdleOptions = {
idleTimeout: 1000,
finalTimeout: 600000,
};
export const startIdleNavigationSpan = (startSpanOption, { finalTimeout = defaultIdleOptions.finalTimeout, idleTimeout = defaultIdleOptions.idleTimeout, } = {}) => {
const client = getClient();
if (!client) {
logger.warn(`[startIdleNavigationSpan] Can't create route change span, missing client.`);
return undefined;
}
const activeSpan = getActiveSpan();
clearActiveSpanFromScope(getCurrentScope());
if (activeSpan && isRootSpan(activeSpan) && isSentryInteractionSpan(activeSpan)) {
logger.log(`[startIdleNavigationSpan] Canceling ${spanToJSON(activeSpan).op} transaction because of a new navigation root span.`);
activeSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'cancelled' });
activeSpan.end();
}
const finalStartStapOptions = Object.assign(Object.assign({}, getDefaultIdleNavigationSpanOptions()), startSpanOption);
const idleSpan = startIdleSpan(finalStartStapOptions, { finalTimeout, idleTimeout });
logger.log(`[startIdleNavigationSpan] Starting ${finalStartStapOptions.op || 'unknown op'} transaction "${finalStartStapOptions.name}" on scope`);
adjustTransactionDuration(client, idleSpan, finalTimeout);
idleSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_ORIGIN_AUTO_NAVIGATION_CUSTOM);
return idleSpan;
};
/**
* Starts an idle span from `@sentry/core` with React Native application
* context awareness.
*
* - Span will be started with new propagation context.
* - Span will be canceled if the app goes to background.
*/
export const startIdleSpan = (startSpanOption, { finalTimeout, idleTimeout }) => {
const client = getClient();
if (!client) {
logger.warn(`[startIdleSpan] Can't create idle span, missing client.`);
return new SentryNonRecordingSpan();
}
getCurrentScope().setPropagationContext(generatePropagationContext());
const span = coreStartIdleSpan(startSpanOption, { finalTimeout, idleTimeout });
cancelInBackground(client, span);
return span;
};
/**
* Returns the default options for the idle navigation span.
*/
export function getDefaultIdleNavigationSpanOptions() {
return {
name: DEFAULT_NAVIGATION_SPAN_NAME,
op: 'navigation',
forceTransaction: true,
scope: getCurrentScope(),
};
}
/**
* Checks if the span is a Sentry User Interaction span.
*/
export function isSentryInteractionSpan(span) {
return [SPAN_ORIGIN_AUTO_INTERACTION, SPAN_ORIGIN_MANUAL_INTERACTION].includes(spanToJSON(span).origin);
}
export const SCOPE_SPAN_FIELD = '_sentrySpan';
/**
* Removes the active span from the scope.
*/
export function clearActiveSpanFromScope(scope) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete scope[SCOPE_SPAN_FIELD];
}
/**
* Ensures that all created spans have an operation name.
*/
export function addDefaultOpForSpanFrom(client) {
client.on('spanStart', (span) => {
if (!spanToJSON(span).op) {
span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'default');
}
});
}
export const SPAN_THREAD_NAME = 'thread.name';
export const SPAN_THREAD_NAME_MAIN = 'main';
export const SPAN_THREAD_NAME_JAVASCRIPT = 'javascript';
/**
* Adds Javascript thread info to spans.
* Ref: https://reactnative.dev/architecture/threading-model
*/
export function addThreadInfoToSpan(client) {
client.on('spanStart', (span) => {
var _a;
if (!((_a = spanToJSON(span).data) === null || _a === void 0 ? void 0 : _a[SPAN_THREAD_NAME])) {
span.setAttribute(SPAN_THREAD_NAME, SPAN_THREAD_NAME_JAVASCRIPT);
}
});
}
/**
* Sets the Main thread info to the span.
*/
export function setMainThreadInfo(spanJSON) {
spanJSON.data = spanJSON.data || {};
spanJSON.data[SPAN_THREAD_NAME] = SPAN_THREAD_NAME_MAIN;
return spanJSON;
}
//# sourceMappingURL=span.js.map