---
title: "Automatic Instrumentation"
description: "Learn what transactions are captured after tracing is enabled."
url: https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation/
---

# Automatic Instrumentation | Sentry for React Native

`@sentry/react-native` provides automatic performance instrumentation out of the box when [tracing is enabled](https://docs.sentry.io/platforms/react-native/tracing.md).

## [Set Up](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#set-up)

To make the most out of our automatic instrumentation, you should:

### [Wrap Your Root Component](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#wrap-your-root-component)

Wrap your root component with Sentry to access the most Performance features.

`App.js`

```javascript
export default Sentry.wrap(App);
```

### [Enable Routing Instrumentation](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#enable-routing-instrumentation)

When no routing instrumentation is used, a transaction for `App Start` is automatically captured. However, that transaction stops being sent when one of the routing integrations below is added. Instead, the `App Start` information is included as a span in a transaction captured by the routing instrumentation.

We currently provide three routing instrumentations out of the box to instrument route changes for:

* [Expo Router](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/expo-router.md)
* [React Navigation](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/react-navigation.md)
* [React Native Navigation](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/react-native-navigation.md)

### [Additional Instrumentation](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#additional-instrumentation)

* [Custom Navigation](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/custom-navigation.md) to add the custom navigation library integration
* [Custom Instrumentation](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/custom-navigation.md) to add custom performance data to your application

## [Features](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#features)

Sentry offers the following automatic instrumentation features.

### [App Start Instrumentation](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#app-start-instrumentation)

The App Start Instrumentation provides insight into how long your application takes to launch. It tracks the length of time from the **earliest native process initialization** until the **React Native root component mounts**.

If you don't [wrap your root component with Sentry](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#wrap-your-root-component), the App Start measurement will finish when the JavaScript code is initialized instead of when the first component mount.

The SDK differentiates between a cold and a warm start, but doesn't track hot starts or resumes. The measurements are available under `measurements.app_start_warm` and `measurements.app_start_cold`.

Cold and warm start are Mobile Vitals, which you can learn about in the [full documentation](https://docs.sentry.io/product/insights/mobile/mobile-vitals.md).

Sentry's App Start instrumentation aims to be as comprehensive and representative of the user experience as possible, and adheres to guidelines by the platform vendors. For this reason, App Starts reported by Sentry might be longer than what you see in other tools. Read more on the [Apple App Start docs](https://docs.sentry.io/platforms/apple/guides/ios/tracing/instrumentation/automatic-instrumentation.md#app-start-tracing) and [Android App Start docs](https://docs.sentry.io/platforms/android/tracing/instrumentation/automatic-instrumentation.md#app-start-instrumentation).

### [Slow and Frozen Frames](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#slow-and-frozen-frames)

Unresponsive UI and animation hitches annoy users and degrade the user experience. Two measurements to track these types of experiences are slow frames and frozen frames. If you want your app to run smoothly, you should try to avoid both. The SDK adds these two measurements for the transactions you capture.

Slow and frozen frames are Mobile Vitals, which you can learn about in the [full documentation](https://docs.sentry.io/product/insights/mobile/mobile-vitals.md).

React Native mobile apps will not report [Web Vitals](https://docs.sentry.io/product/insights/web-vitals.md). These values depend on APIs provided by browsers, and are not available in this context.

#### [AndroidX Support](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#androidx-support)

Sentry uses the `androidx.core` library for detecting [slow and frozen frames](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#slow-and-frozen-frames). This is necessary to produce accurate results across all Android OS versions.

We check for availability at runtime, so if you're not using `androidx.core`, you can remove it from Sentry's transitive dependencies.

```Groovy
api ('io.sentry:sentry-android:8.38.0') {
    exclude group: 'androidx.core', module: 'core'
}
```

Note that if you remove this transitive dependency, slow and frozen frames won't be reported.

### [Stall Tracking](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#stall-tracking)

A stall is when the JavaScript event loop takes longer than expected to complete. A stall in your JavaScript code will not just make your UI unresponsive, but also slow down the logic that is contained within JavaScript. This slows everything down, creating a bad experience for your users.

We track stalls that occur in your React Native app during a transaction and provide you with these values:

* **Longest Stall Time**: The time, in milliseconds, of the longest event loop stall.
* **Total Stall Time**: The total combined time, in milliseconds, of all stalls.
* **Stall Count**: The total number of stalls that occurred during the transaction.

### [Fetch/XML Request Instrumentation](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#fetchxml-request-instrumentation)

The tracing integration creates a child span for every `XMLHttpRequest` or `fetch` request on the JavaScript layer that occurs while those transactions are open. Learn more about [traces, transactions, and spans](https://docs.sentry.io/product/sentry-basics/tracing/distributed-tracing.md).

## [Configuration Options](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#configuration-options)

To configure the automatic performance instrumentation, you will need to add the `ReactNativeTracing` integration yourself. We provide many options by default, so for the majority of apps you won't need to configure the integration yourself.

```javascript
import * as Sentry from "@sentry/react-native";

Sentry.init({
  dsn: "___PUBLIC_DSN___",

  integrations: [Sentry.reactNativeTracingIntegration()],
});
```

### [tracePropagationTargets](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#tracepropagationtargets)

The default value of `tracePropagationTargets` is `[/.*/]` for mobile and `['localhost', /^\//]` for web. The React Native SDK will attach the `sentry-trace` header to all outgoing XHR/fetch requests on mobile. On web, trace data is only attached to outgoing requests that contain `localhost` in their URL or requests whose URL starts with a `'/'` (for example `GET /api/v1/users`).

Using React Native on Web? Here is how \`tracePropagationTargets\` changes.

The SDK will attach the `sentry-trace` header to all outgoing XHR/fetch requests whose destination contains a string in the list or matches a regex in the list. If your frontend is making requests to a different domain, you'll need to add the domain there to propagate the `sentry-trace` header to the backend services, which is required to link transactions together as part of a single trace. **The `tracePropagationTargets` option matches against the entire request URL, not just the domain. Using stricter regex to match certain parts of the URL ensures that requests don't unnecessarily have the `sentry-trace` header attached.**

For example:

* A frontend application is served from `example.com`
* A backend service is served from `api.example.com`
* The frontend application makes API calls to the backend
* Therefore, the option needs to be configured like this: `Sentry.init({tracePropagationTargets: ['api.example.com']})`
* Now outgoing XHR/fetch requests to `api.example.com` will get the `sentry-trace` header attached

```javascript
Sentry.init({
  dsn: "___PUBLIC_DSN___",
  tracePropagationTargets: ["localhost", "my-site-url.com"],

  // We recommend adjusting this value in production, or using tracesSampler
  // for finer control
  tracesSampleRate: 1.0,
});
```

You'll need to configure your web server CORS to allow the `sentry-trace` header. The configuration might look like `"Access-Control-Allow-Headers: sentry-trace"`, but the configuration depends on your setup. If you don't allow the `sentry-trace` header, the request might get blocked.

### [beforeStartSpan](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#beforestartspan)

`beforeStartSpan` is called at the start of every `pageload` or `navigation` span, and is passed an object containing data about the span which will be started. With `beforeStartSpan` you can modify that data.

```javascript
Sentry.init({
  dsn: "___PUBLIC_DSN___",
  integrations: [
    Sentry.reactNativeTracingIntegration({
      beforeStartSpan: (context) => {
        return {
          ...context,
          attributes: {
            ...context.attributes,
            custom: "value",
          },
        };
      },
    }),
  ],
});
```

### [shouldCreateSpanForRequest](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#shouldcreatespanforrequest)

This function can be used to filter out unwanted spans such as XHRs running health checks or something similar. If this function isn't specified, spans will be created for all requests.

```javascript
Sentry.init({
  // ...
  integrations: [
    Sentry.reactNativeTracingIntegration({
      shouldCreateSpanForRequest: (url) => {
        // Do not create spans for outgoing requests to a `/health/` endpoint
        return !url.match(/\/health\/?$/);
      },
    }),
  ],
});
```

### [idleTimeoutMs](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#idletimeoutms)

The amount of idle time, measured in ms, you have to wait for the transaction to finish if there are no unfinished spans. The transaction will use the end timestamp of the last finished span as the endtime for the transaction.

The default is `1_000`.

### [finalTimeoutMs](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#finaltimeoutms)

The maximum duration of the transaction, measured in ms. If the transaction duration hits the `finalTimeout` value, it will be done.

The default is `60_0000`.

## [Recipes](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#recipes)

Currently, by default, the React Native SDK will only create child spans for fetch/XHR transactions out of the box. This means once you are done setting up your routing instrumentation, you will either see just a few fetch/XHR child spans or no children at all. To find out how to customize instrumentation your app, review our [Custom Instrumentation](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/custom-instrumentation.md).

### [React Profiler](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#react-profiler)

We export the React Profiler from our React Native SDK as well. Learn more in [React Component Tracking](https://docs.sentry.io/platforms/javascript/guides/react/features/component-monitoring.md).

After you instrument your app's routing, if you wrap a component that renders on one of the routes with `withProfiler`, you will be able to track the component's lifecycle as a child span of the route transaction.

```javascript
import * as Sentry from "@sentry/react-native";

// withProfiler HOC
const SomeComponent = () => {
  // ...
};

export default Sentry.withProfiler(SomeComponent);
```

#### [Minified Names in Production](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#minified-names-in-production)

When bundling for production, React Native will minify class and function names to reduce the bundle size. This means that **you won't get the full original component names in your Profiler spans** and instead you will see minified names. Check out our [troubleshooting guide for minified production bundles](https://docs.sentry.io/platforms/react-native/troubleshooting.md#minified-names-in-production) documentation to solve this.

## [Opt Out](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#opt-out)

If you want to use tracing without our automatic instrumentation, you can disable it by setting `enableAutoPerformanceTracing` in your Sentry options and removing the `ReactNativeTracing` integration, if you added it:

```javascript
import * as Sentry from "@sentry/react-native";

Sentry.init({
  dsn: "___PUBLIC_DSN___",

  enableAutoPerformanceTracing: false,
});
```

## [User Interaction Instrumentation](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation.md#user-interaction-instrumentation)

The UI instrumentation captures transactions and adds breadcrumbs for touch interactions. Gesture support using React Native Gesture Handler is also available with the `sentryTraceGesture` wrapper. Learn more about [User Interaction Instrumentation](https://docs.sentry.io/platforms/react-native/tracing/instrumentation/user-interaction-instrumentation.md).
