# Automatic Instrumentation | Sentry for React

Capturing spans requires that you first [set up tracing in your app](https://docs.sentry.io/platforms/javascript/guides/react/tracing.md) if you haven't already.

The Sentry SDK provides a `BrowserTracing` integration to add automatic instrumentation for monitoring the performance of browser applications.

## [What Our Instrumentation Provides](https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation.md#what-our-instrumentation-provides)

The `BrowserTracing` integration creates a new transaction for each page load and navigation event, and creates a child span for every `XMLHttpRequest` or `fetch` request that occurs while those transactions are open.

If you are using `react-router` in your application, you need to use our [`react-router` instrumentation](https://docs.sentry.io/platforms/javascript/guides/react/configuration/integrations/react-router.md) to be able to trace `navigation` events.

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

To enable tracing, include `browserTracingIntegration` in your SDK configuration options.

To use `react-router` integration, import and set a custom routing instrumentation using a custom history. Make sure you use a `Router` component combined with `createBrowserHistory` (or equivalent).

```javascript
import { Router } from "react-router-dom";
import { createBrowserHistory } from "history";

import * as Sentry from "@sentry/react";

const history = createBrowserHistory();

Sentry.init({
  dsn: "___PUBLIC_DSN___",

  integrations: [
    Sentry.reactRouterV5BrowserTracingInstrumentation({ history }),
      // You can also use one of:
      // * reactRouterV3BrowserTracingInstrumentation
      // * reactRouterV4BrowserTracingInstrumentation
      // * reactRouterV6BrowserTracingInstrumentation
      // or just browserTracingIntegration
    }),
  ],

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

Now you should be generating `pageload`/`navigation` transactions from the `BrowserTracing` integration, using Sentry's [`react-router` instrumentation](https://docs.sentry.io/platforms/javascript/guides/react/configuration/integrations/react-router.md).

### [Custom Routing](https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation.md#custom-routing)

By default, the `browserTracingIntegration()` will create a `pageload` span for when the page is initially loaded, as well as a `navigation` span for whenever the URL changes afterwards.

To make sure that spans are created correctly for a custom routing setup, you'll need to opt out of the default span creation by setting `instrumentNavigation: false` and `instrumentPageLoad: false` in the `browserTracingIntegration()` options. You can then manually create spans like this:

```javascript
const client = Sentry.init({
  integrations: [
    Sentry.browserTracingIntegration({
      // disable automatic span creation
      instrumentNavigation: false,
      instrumentPageLoad: false,
    }),
  ],
});

// We start the pageload span as early as possible!
let pageLoadSpan = Sentry.startBrowserTracingPageLoadSpan(client, {
  name: window.location.pathname,
  attributes: {
    [Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
  },
});

// Somewhere, instrument your router like this:
myRouter.on("routeChange", (route) => {
  // Make sure that the pageload span uses the route name
  // After that, each route change should trigger a navigation span (which will automatically finish the previous one)
  if (pageLoadSpan) {
    pageLoadSpan.updateName(route.name);
    pageLoadSpan.setAttribute(
      Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
      "route",
    );
    pageLoadSpan = undefined;
  } else {
    Sentry.startBrowserTracingNavigationSpan(client, {
      op: "navigation",
      name: route.name, // or what the name of the span should be
      attributes: {
        [Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "route",
      },
    });
  }
});
```

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

Supported options:

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

| Type    | `Array<string \| RegExp>` |
| ------- | ------------------------- |
| Default | `['localhost', /^\/$/]`   |

The `tracingOrigins` option was renamed `tracePropagationTargets` and deprecated in [version `7.19.0`](https://github.com/getsentry/sentry-javascript/releases/tag/7.19.0) of the JavaScript SDK. `tracingOrigins` will be removed in version 8.

A list of strings and regular expressions. The JavaScript SDK will attach the `sentry-trace` and `baggage` headers 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 it there to propagate the `sentry-trace` and `baggage` headers to the backend services, which is required to link spans together as part of a single trace.

**The `tracePropagationTargets` option matches 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 additional headers attached.**

The default value of `tracePropagationTargets` is `['localhost', /^\//]`. This means that by default, tracing headers are only attached to requests that contain `localhost` in their URL or requests whose URL starts with a `'/'` (for example `GET /api/v1/users`).

For example:

* A frontend application is served from `example.com`.
* A backend service is served from `api.example.com`.
* During development, the backend service is served from `localhost`.
* The frontend application makes API calls to the backend.
* Set the `tracePropagationTargets` option to `["localhost", /^https:\/\/api\.example\.com/]`.
* Now outgoing XHR/fetch requests to your backend service will get the `sentry-trace` and `baggage` headers attached.

```javascript
Sentry.init({
  // ...
  integrations: [Sentry.browserTracingIntegration()],

  // Set `tracePropagationTargets` to control for which URLs trace propagation should be enabled
  tracePropagationTargets: ["localhost", /^https:\/\/yourserver\.io\/api/],
});
```

You will need to configure your web server [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers) to allow the `sentry-trace` and `baggage` headers. The configuration might look like `"Access-Control-Allow-Headers: sentry-trace"` and `"Access-Control-Allow-Headers: baggage"`, but it depends on your set up. If you do not allow the two headers, the request might be blocked.

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

| Type | `(options: StartSpanOptions) => StartSpanOptions` |
| ---- | ------------------------------------------------- |

`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.

One common use case is parameterizing transaction names. For both `pageload` and `navigation` transactions, the `browserTracingIntegration` uses the browser's `window.location` value to generate a transaction name. Using `beforeStartSpan` lets you modify the transaction name to make it more generic, so that for example, transactions named `GET /users/12312012` and `GET /users/11212012` can both be renamed to `GET /users/:userid`. That way they'll be grouped together.

```javascript
Sentry.init({
  // ...
  integrations: [
    Sentry.browserTracingIntegration({
      beforeStartSpan: (context) => {
        return {
          ...context,
          // You could use your UI's routing library to find the matching
          // route template here. We don't have one right now, so do some basic
          // parameter replacements.
          name: location.pathname
            .replace(/\/[a-f0-9]{32}/g, "/<hash>")
            .replace(/\/\d+/g, "/<digits>"),
        };
      },
    }),
  ],
});
```

If you're using React, read our docs to learn how to set up your [React Router integration](https://docs.sentry.io/platforms/javascript/guides/react/configuration/integrations/react-router.md).

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

| Type | `(url: string) => boolean` |
| ---- | -------------------------- |

This function can be used to filter out unwanted spans such as XHRs running health checks or something similar.

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

By default, spans will be created for all requests.

### [onRequestSpanStart](https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation.md#onRequestSpanStart)

| Type | `(span: Span, requestInformation: { headers?: WebFetchHeaders }): void` |
| ---- | ----------------------------------------------------------------------- |

This callback is invoked directly after a span is started for an outgoing fetch or XHR request. You can use it to annotate the span with additional data or attributes, for example by setting attributes based on the passed request headers.

### [idleTimeout](https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation.md#idleTimeout)

| Type    | `number` |
| ------- | -------- |
| Default | `1000`   |

The idle time, measured in ms, to wait until the pageload/navigation span will be finished, if there are no unfinished spans. The pageload/navigation span will use the end timestamp of the last finished span as the endtime.

### [finalTimeout](https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation.md#finalTimeout)

| Type    | `number` |
| ------- | -------- |
| Default | `30000`  |

The maximum duration of the pageload/naivgation span, measured in ms. If the duration exceeds the `finalTimeout` value, it will be finished.

### [childSpanTimeout](https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation.md#childSpanTimeout)

| Type    | `number` |
| ------- | -------- |
| Default | `15000`  |

The time, measured in ms, that a child span may run. If the last started child span is still running for more than this time, the pageload/navigation span will be finished.

### [instrumentNavigation](https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation.md#instrumentNavigation)

| Type    | `boolean` |
| ------- | --------- |
| Default | `true`    |

This flag enables or disables creation of `navigation` span on history changes.

### [instrumentPageLoad](https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation.md#instrumentPageLoad)

| Type    | `boolean` |
| ------- | --------- |
| Default | `true`    |

This flag enables or disables creation of `pageload` span on first pageload.

### [enableReportPageLoaded](https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation.md#enableReportPageLoaded)

| Available since | `10.13.0` |
| --------------- | --------- |
| Type            | `boolean` |
| Default         | `false`   |

This option determines whether the [`Sentry.reportPageLoaded()` function](https://docs.sentry.io/platforms/javascript/guides/react/apis.md#reportPageLoaded) is enabled.

### [markBackgroundSpan](https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation.md#markBackgroundSpan)

| Type    | `boolean` |
| ------- | --------- |
| Default | `true`    |

This option flags pageload/navigation spans when tabs are moved to the background with "cancelled". Because browser background tab timing is not suited for precise measurements of operations and can affect your statistics in nondeterministic ways, we recommend that this option be enabled.

### [enableLongTask](https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation.md#enableLongTask)

| Type    | `boolean` |
| ------- | --------- |
| Default | `true`    |

This option determines whether spans for long tasks automatically get created.

### [enableLongAnimationFrame](https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation.md#enableLongAnimationFrame)

| Available since | `8.18.0`  |
| --------------- | --------- |
| Type            | `boolean` |
| Default         | `true`    |

This option determines whether spans for long animation frames get created automatically. If both `enableLongAnimationFrame` and [`enableLongTask`](https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation.md#enableLongTask) are enabled, Sentry will send long animation frames and fallback to long tasks (if long animation frames aren't supported by the browser).

### [enableInp](https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation.md#enableInp)

| Available since | `7.104.0`                         |
| --------------- | --------------------------------- |
| Type            | `boolean`                         |
| Default         | `true` (<!-- -->See note<!-- -->) |

This option determines whether interactions spans automatically get created when an [Interaction to Next Paint (INP)](https://docs.sentry.io/product/insights/web-vitals/web-vitals-concepts.md#interaction-to-next-paint-inp) event is detected. Interactions are scored and surfaced in the [Web Vitals](https://docs.sentry.io/product/insights/web-vitals.md) module.

The default is `true` starting with SDK version `8.x` and `false` in `7.x`.

INP samples currently incur no cost to enable at Sentry. Basic samples contain limited information such as the interaction target, latency, and user. You may wish to enrich your INP samples by setting up [Session Replays](https://docs.sentry.io/platforms/javascript/session-replay.md) and/or setting up [Browser Profiling](https://docs.sentry.io/platforms/javascript/profiling.md) instrumentation around your interactive elements to gain further insights into your slowest interactions.

Please note that any Session Replays and Browser Profiles used this way will incur their [standard cost](https://docs.sentry.io/pricing.md#per-category-pricing) depending on your plan and are subject to the sampling rates configured.

```javascript
Sentry.init({
  // ...
  integrations: [
    Sentry.browserTracingIntegration({
      enableInp: true,
    }),
  ],
});
```

### [interactionsSampleRate](https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation.md#interactionsSampleRate)

| Type    | `number` |
| ------- | -------- |
| Default | `1.0`    |

This option determines the sample rate of INP spans. `interactionsSampleRate` is applied on top of `tracesSampleRate`, therefore if your `interactionsSampleRate` is set to `0.5` and your `tracesSampleRate` is set to `0.1`, the outcome will be `0.05`.

The default is `1.0`.

### [ignoreResourceSpans](https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation.md#ignoreResourceSpans)

| Available since | `9.23.0`        |
| --------------- | --------------- |
| Type            | `Array<string>` |
| Default         | `[]`            |

This option determines which categories or resource spans should be ignored. The resource categories are the span `op`s (for example `resource.script` or `resource.img`)

```JavaScript
Sentry.init({
  // ...
  integrations: [
    Sentry.browserTracingIntegration({
      ignoreResourceSpans: ['resource.css', 'resource.script'],
    }),
  ],
});
```

By default, all resource spans are captured.

### [ignorePerformanceApiSpans](https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation.md#ignorePerformanceApiSpans)

| Available since | `9.23.0`                  |
| --------------- | ------------------------- |
| Type            | `Array<string \| RegExp>` |
| Default         | `[]`                      |

This option allows you to ignore certain spans created from the following browser Performance APIs:

* [`performance.mark(...)`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/mark)
* [`performance.measure(...)`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/measure)

Any mark or measure entries matching the strings or regular expressions in the passed array will not be emitted as `mark` or `measure` spans.

```JavaScript
Sentry.init({
  integrations: [
    Sentry.browserTracingIntegration({
      ignorePerformanceApiSpans: ['myMeasurement', /myMark/],
    }),
  ],
});

// no spans will not be created for these:
performance.mark('myMark');
performance.measure('myMeasurement');

// spans will be created for these:
performance.mark('authenticated');
performance.measure('input-duration', ...);
```

By default, all performance API spans are captured.
