diff --git a/docs/platforms/react-native/enriching-events/context/index.mdx b/docs/platforms/react-native/enriching-events/context/index.mdx
index cb533c9061010..fc9fe8ff41ed7 100644
--- a/docs/platforms/react-native/enriching-events/context/index.mdx
+++ b/docs/platforms/react-native/enriching-events/context/index.mdx
@@ -89,6 +89,7 @@ Sentry.captureException(new Error("something went wrong"), () => scope);
Context is held in the current scope and thus is cleared when the scope is removed ("popped"). You can push and pop your own scopes to apply context data to a specific code block or function.
+
Sentry supports two different ways for unsetting context:
1. Modifying, overwriting or clearing values on the current scope.
@@ -100,10 +101,10 @@ With the following snippet, the `user` context will be updated for all future ev
Sentry.setUser(someUser);
```
-If you want to remove data from the current scope, you can call:
+If you want to remove all data from the current scope, you can call:
```javascript
-Sentry.configureScope((scope) => scope.clear());
+Sentry.getCurrentScope().clear();
```
The following will only configure the `user` context for the error captured inside the `withScope` callback. The context will be automatically restored to the previous state afterwards:
diff --git a/docs/platforms/react-native/enriching-events/scopes/index.mdx b/docs/platforms/react-native/enriching-events/scopes/index.mdx
index b7491c6792745..bc9052571091b 100644
--- a/docs/platforms/react-native/enriching-events/scopes/index.mdx
+++ b/docs/platforms/react-native/enriching-events/scopes/index.mdx
@@ -1,46 +1,110 @@
---
-title: Scopes and Hubs
+title: Scopes
description: "SDKs will typically automatically manage the scopes for you in the framework integrations. Learn what a scope is and how you can use it to your advantage."
---
When an event is captured and sent to Sentry, SDKs will merge that event data with extra
information from the current scope. SDKs will typically automatically manage the scopes
for you in the framework integrations and you don't need to think about them. However,
-you should know what a scope is and how you can use it for your advantage.
+you should know what a scope is and how you can use it to your advantage.
-## What's a Scope, What's a Hub
+## What's a Scope?
-You can think of the hub as the central point that our SDKs use to route an
-event to Sentry. When you call `init()` a hub is created and a client and a
-blank scope are created on it. That hub is then associated with the current
-thread and will internally hold a stack of scopes.
-
-The scope will hold useful information that should be sent along with the
-event. For instance [contexts](../context/) or
+Scopes hold useful information that gets sent along with the
+event. For instance, [contexts](../context/) and
[breadcrumbs](../breadcrumbs/) are stored on
-the scope. When a scope is pushed, it inherits all data from the parent scope
-and when it pops all modifications are reverted.
+the scope. When a scope is forked, it inherits all data from its parent scope.
+
+The default SDK integrations will fork scopes intelligently. For
+instance, web framework integrations will fork scopes around your
+routes or request handlers.
+
+## How Scopes Work
+
+Scopes are basically stacks of data that are attached to events. When an event is captured, the SDK will merge the data from the active scopes into the event. This allows you to attach data to events that is relevant to the context in which the event was captured.
+
+A scope is generally valid inside of a callback or an execution context. This means that multiple parts of your application may have different scopes active at the same time. For instance, a web server might handle multiple requests at the same time, and each request may have different scope data to apply to its events.
+
+## Different Kinds of Scopes
+
+The Sentry SDK has three different kinds of scopes:
+
+- [Global scope](#global-scope)
+- [Isolation scope](#isolation-scope)
+- [Current scope](#current-scope)
+
+### Global Scope
+
+The global scope is applied to _all_ events, no matter where they originate. You can use it to store data that should apply to all events, such as environmental information.
+
+You can access the global scope via `Sentry.getGlobalScope()`.
+
+Note, that the global scope can only be used to write data, not to capture events. Events can only be captured on the current scope (for example, `getCurrentScope().captureException()` and similar APIs).
+
+### Isolation Scope
+
+The isolation scope is used to isolate events from each other. For example, each request in a web server might get its own isolation scope, so that events from one request don't interfere with events from another. In most cases, you'll want to put data that should be applied to your events on the isolation scope. This is why all `Sentry.setXXX` methods, like `Sentry.setTag()` will write data onto the currently active isolation scope. A classic example of data that belongs on the isolation scope is user data, where each request may have a different user, so you'd want to make sure that the user is set on the isolation scope.
-The default SDK integrations will push and pop scopes intelligently. For
-instance web framework integrations will create and destroy scopes around your
-routes or controllers.
+You can access the isolation scope via `Sentry.getIsolationScope()`, but usually you'll just use the `Sentry.setXXX` methods to set data on the currently active isolation scope:
-## How the Scope and Hub Work
+```javascript
+Sentry.setTag("my-tag", "my value");
+// Is identical to:
+Sentry.getIsolationScope().setTag("my-tag", "my value");
+```
-As you start using an SDK, a scope and hub are automatically created for you out
-of the box. It's unlikely that you'll interact with the hub directly unless you're
-writing an integration or you want to create or destroy scopes. Scopes, on the
-other hand are more user facing. You can call at any point in
-time to modify data stored on the scope. This is useful for doing things like
-[modifying the context](../context/).
+
+In the browser, the isolation scope is never forked because it's impossible to keep track of where an isolation scope would belong. This is why the isolation scope is effectively global in the browser.
+
-When you call a global function such as internally Sentry
-discovers the current hub and asks it to capture an event. Internally the hub will
-then merge the event with the topmost scope's data.
+Note, that the isolation scope can only be used to write data, not to capture events. Events can only be captured on the current scope (for example, `getCurrentScope().captureException()` and similar APIs).
+
+### Current Scope
+
+Current scope is the local scope that's currently active. Unlike the rarely-forked isolation scope, the current scope may be forked more frequently and under the hood. It can be used to store data that should only be applied to specific events. In most cases, you shouldn't access this scope directly, but use `Sentry.withScope` to create a new scope that's only active for a specific part of your code:
+
+```javascript
+Sentry.withScope((scope) => {
+ // scope is the current scope inside of this callback!
+ scope.setTag("my-tag", "my value");
+ // this tag will only be applied to events captured inside of this callback
+ // the following event will have the tag:
+ Sentry.captureException(new Error("my error"));
+});
+// this event will not have the tag:
+Sentry.captureException(new Error("my other error"));
+```
+
+You can access the current scope via `Sentry.getCurrentScope()`, but you should use `Sentry.withScope()` to interact with local scopes in most cases instead.
+
+## How Scope Data is Applied to Events
+
+Before an event (like an error or transaction) is sent to Sentry, the currently active scopes are applied to it.
+
+The global scope is applied first, followed by the isolation scope, and finally the current scope. This means that any data set on the current scope will take precedence over data set on the isolation and global scopes:
+
+```javascript
+Sentry.getGlobalScope().setExtras({
+ shared: "global",
+ global: "data",
+});
+Sentry.getIsolationScope().setExtras({
+ shared: "isolation",
+ isolation: "data",
+});
+Sentry.getCurrentScope().setExtras({
+ shared: "current",
+ current: "data",
+});
+
+Sentry.captureException(new Error("my error"));
+// --> Will have the following extra:
+// { shared: 'current', global: 'data', isolation: 'data', current: 'data' }
+```
## Configuring the Scope
-The most useful operation when working with scopes is the function. It can be used to reconfigure the current scope.
+There are two main ways to interact with the scope. You can access the current scope via `Sentry.getCurrentScope()` and use setters on the resulting scope, or you can use global methods like `Sentry.setTag()` directly, which will set on the respective scope under the hood (this will be the isolation scope).
You'll first need to import the SDK, as usual:
@@ -48,31 +112,32 @@ You'll first need to import the SDK, as usual:
You can, for instance, add custom tags or inform Sentry about the currently authenticated user.
-
-
-You can also apply this configuration when unsetting a user at logout:
-
-
+```javascript
+/// Usually, you don't want to write on the current scope, so use with care!
+const scope = Sentry.getCurrentScope();
+scope.setTag("my-tag", "my value");
+scope.setUser({
+ id: 42,
+ email: "john.doe@example.com",
+});
+
+// Or use the global methods (which will set data on the isolation scope):
+Sentry.setTag("my-tag", "my value");
+Sentry.setUser({
+ id: 42,
+ email: "john.doe@example.com",
+});
+```
To learn what useful information can be associated with scopes see
-[the context documentation](../context/).
+[context](../context/), [tags](../tags), [users](../identify-user) and [breadcrumbs](../breadcrumbs/).
-## Local Scopes
-
-We also support pushing and configuring a scope within a single call. This is typically
-called , or implemented as a function parameter on the capture methods, depending on the SDK. It's very helpful if
-you only want to send data for one specific event.
-
-### Using
+## Using `withScope`
In the following example we use to attach a `level` and a `tag` to only one specific error:
-While this example looks similar to , it is actually very different.
-Calls to change the current active scope; all successive calls to will maintain previously set changes unless they are explicitly unset.
-
-On the other hand, creates a clone of the current scope, and the changes
-made will stay isolated within the callback function. This allows you to
+The scope inside the `withScope()` callback is only valid inside of the callback. Once the callback ends, the scope will be removed and will no longer apply. The inner scope is only applied to events that are captured inside of the callback. `withScope()` will clone (or fork) the current scope, so the current scope won't be modified. This allows you to
more easily isolate pieces of context information to specific locations in your code or
even call to briefly remove all context information.
diff --git a/docs/platforms/react-native/enriching-events/transaction-name/index.mdx b/docs/platforms/react-native/enriching-events/transaction-name/index.mdx
index 252a245f8d31b..3d4b603d5b24e 100644
--- a/docs/platforms/react-native/enriching-events/transaction-name/index.mdx
+++ b/docs/platforms/react-native/enriching-events/transaction-name/index.mdx
@@ -22,10 +22,14 @@ A lot of our framework integrations already set a transaction name, though you c
You'll first need to import the SDK, as usual:
-
+```javascript
+import * as Sentry from "@sentry/react-native";
+```
To override the name of the currently running transaction:
-
+```javascript
+Sentry.getCurrentScope().setTransactionName("UserListView");
+```
Please refer to [the tracing documentation](../../tracing/) for how to start and stop transactions.
diff --git a/docs/platforms/react-native/index.mdx b/docs/platforms/react-native/index.mdx
index 2d1ef4768d228..e152b4e6d6a6a 100644
--- a/docs/platforms/react-native/index.mdx
+++ b/docs/platforms/react-native/index.mdx
@@ -38,7 +38,7 @@ Sentry captures data by using an SDK within your application's runtime. These ar
To install, run `@sentry/wizard`:
```bash {tabTitle:npm}
-npx @sentry/wizard@latest -s -i reactNative
+npx @sentry/wizard@latest -i reactNative
```
[Sentry Wizard](https://github.com/getsentry/sentry-wizard) will patch your project accordingly, though you can [set up manually](/platforms/react-native/manual-setup/manual-setup/) if you prefer. You only need to patch the project once. Then you can add the patched files to your version control system.
@@ -65,7 +65,7 @@ If you're using Expo, [read our docs](/platforms/react-native/manual-setup/expo/
To capture all errors, initialize the Sentry React Native SDK as soon as possible.
-```javascript {filename:App.js} {"onboardingOptions": {"performance": "5-7", "profiling": "8-12"}}
+```javascript {filename:App.js} {"onboardingOptions": {"performance": "5-7", "profiling": "8-10"}}
import * as Sentry from "@sentry/react-native";
Sentry.init({
@@ -73,11 +73,9 @@ Sentry.init({
// Set tracesSampleRate to 1.0 to capture 100% of transactions for tracing.
// We recommend adjusting this value in production.
tracesSampleRate: 1.0,
- _experiments: {
- // profilesSampleRate is relative to tracesSampleRate.
- // Here, we'll capture profiles for 100% of transactions.
- profilesSampleRate: 1.0,
- },
+ // profilesSampleRate is relative to tracesSampleRate.
+ // Here, we'll capture profiles for 100% of transactions.
+ profilesSampleRate: 1.0,
});
```
diff --git a/docs/platforms/react-native/integrations/custom.mdx b/docs/platforms/react-native/integrations/custom.mdx
index b80f22829f18e..81babd6b731d0 100644
--- a/docs/platforms/react-native/integrations/custom.mdx
+++ b/docs/platforms/react-native/integrations/custom.mdx
@@ -1,7 +1,115 @@
---
title: Custom Integrations
+sidebar_order: 200
description: "Learn how to enable a custom integration."
-sidebar_order: 3
---
-
+In addition to the integrations that come with the SDK, you can also write custom integrations.
+
+Custom integration must conform to the [Integration interface](https://github.com/getsentry/sentry-javascript/blob/master/packages/types/src/integration.ts).
+
+A custom integration can be created and added to the SDK as follows:
+
+```javascript
+function myAwesomeIntegration() {
+ return {
+ name: "MyAwesomeIntegration",
+ setup(client) {
+ // Do something when the SDK is initialized
+ // The client that is being setup is passed to the hook
+ },
+ };
+}
+
+Sentry.init({
+ // ...
+ integrations: [myAwesomeIntegration()],
+});
+```
+
+All hooks on an integration are optional. The only required field is the `name`. You can use one or multiple of the following hooks in a custom integration:
+
+### `setup`
+
+The `setup` hook is called when the SDK is initialized. It receives the client instance as an argument.
+You should use this if you want to run some code upon initialization.
+
+```javascript
+const integration = {
+ name: "MyAwesomeIntegration",
+ setup(client) {
+ setupCustomSentryListener(client);
+ },
+};
+```
+
+### `processEvent`
+
+This hook can be used to modify events before they're sent to Sentry. It receives the event as an argument and should return the modified event. The hook also receives a hint object that may hold additional event metadata, as well as the client that's sending the event. You can also return `null` to drop the event from being sent.
+
+```javascript
+const integration = {
+ name: "MyAwesomeIntegration",
+ processEvent(event, hint, client) {
+ event.extra = {
+ ...event.extra,
+ myCustomTag: "value",
+ };
+ // Return the modified event,
+ // or return `null` to drop the event
+ return event;
+ },
+};
+```
+
+You can also return a promise that resolves with an event or `null`. However, this is not recommended and should be avoided wherever possible, because it can delay event sending.
+
+### `preprocessEvent`
+
+This hook is similar to `processEvent`, but it's called before the event is passed to any other `processEvent` hook. It can be used in places where the order of processing is important.
+
+You can use `processEvent` for most cases, but only when you need to ensure that your hook is called before any other `processEvent` hook use `preprocessEvent`.
+
+Similar to `processEvent`, this hook receives the event, hint, and client as arguments. However, this hook won't allow the return of a modified event or `null` to drop the event. You can only mutate the passed in event in this hook:
+
+```javascript
+const integration = {
+ name: "MyAwesomeIntegration",
+ preprocessEvent(event, hint, client) {
+ event.extra = {
+ ...event.extra,
+ myCustomTag: "value",
+ };
+ // Nothing to return, just mutate the event
+ },
+};
+```
+
+### `setupOnce`
+
+This hook is similar to `setup`, but it's only run once, even if the SDK is re-initialized. It won't receive any arguments. We recommend that you use `setup` instead. The only reason to use `setupOnce` is when you may be calling `Sentry.init()` multiple times and you want to ensure a certain piece of code is only run once.
+
+```javascript
+const integration = {
+ name: "MyAwesomeIntegration",
+ setupOnce() {
+ wrapLibrary();
+ },
+};
+```
+
+### `afterAllSetup`
+
+While we recommend that you use the `setup` hook in most cases, `afterAllSetup` can be used to make sure that all other integrations have been run. This hook receives the `client` that is being set up as the first argument and is triggered after `setupOnce()` and `setup()` have been called for all integrations.
+
+
+```javascript
+const integration = {
+ name: "MyAwesomeIntegration",
+ afterAllSetup(client) {
+ // We can be sure that all other integrations
+ // have run their `setup` and `setupOnce` hooks now
+ startSomeThing(client);
+ },
+};
+```
diff --git a/docs/platforms/react-native/integrations/default.mdx b/docs/platforms/react-native/integrations/default.mdx
index 791a6ba039590..b960c8fdb2343 100644
--- a/docs/platforms/react-native/integrations/default.mdx
+++ b/docs/platforms/react-native/integrations/default.mdx
@@ -9,7 +9,7 @@ The below system integrations are part of the standard library or the interprete
### InboundFilters
-_Import name: `Sentry.Integrations.InboundFilters`_
+_Import name: `Sentry.inboundFiltersIntegration`_
This integration allows you to ignore specific errors based on the type,
message, or URLs in a given exception.
@@ -22,23 +22,13 @@ only work for captured exceptions, not raw message events.
### FunctionToString
-_Import name: `Sentry.Integrations.FunctionToString`_
+_Import name: `Sentry.functionToStringIntegration`_
This integration allows the SDK to provide original functions and method names, even when those functions or methods are wrapped by our error or breadcrumb handlers.
-
-
-### TryCatch
-
-_Import name: `Sentry.Integrations.TryCatch`_
-
-This integration wraps native time and events APIs (`setTimeout`, `setInterval`, `requestAnimationFrame`, `addEventListener/removeEventListener`) in `try/catch` blocks to handle async exceptions.
-
-
-
### Breadcrumbs
-_Import name: `Sentry.Integrations.Breadcrumbs`_
+_Import name: `Sentry.breadcrumbsIntegration`_
This integration wraps native APIs to capture breadcrumbs. By default, the Sentry SDK wraps all APIs.
@@ -71,33 +61,12 @@ Available options:
}
```
-
-
-### GlobalHandlers
+### NativeLinkedErrors
-_Import name: `Sentry.Integrations.GlobalHandlers`_
-
-This integration attaches global handlers to capture uncaught exceptions and unhandled rejections.
-
-Available options:
-
-```javascript
-{
- onerror: boolean;
- onunhandledrejection: boolean;
-}
-```
-
-
-
-### LinkedErrors
-
-_Import name: `Sentry.Integrations.LinkedErrors`_
+_Import name: `Sentry.nativeLinkedErrorsIntegration`_
This integration allows you to configure linked errors which are recursively read up to a specified limit. A lookup by a specific key on the captured Error object is then performed. By default, the integration records up to five errors and the key used for recursion is `"cause"`.
-This integration also enhances captured error events with data from an [AggregateError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError) where applicable, by recursively iterating over the `errors` property on Error objects.
-
Available options:
```javascript
@@ -109,75 +78,43 @@ Available options:
Here's a code example of how this could be implemented:
-
+```javascript
+
}>
@@ -26,7 +26,7 @@ The Sentry Error Boundary is also available as a higher-order component.
```javascript
import React from "react";
-import * as Sentry from "@sentry/react";
+import * as Sentry from "@sentry/react-native";
Sentry.withErrorBoundary(Example, { fallback:
an error has occurred
});
```
@@ -41,7 +41,7 @@ In the example below, when the `` component hits an error, the `
+The Sentry SDK uses integrations to hook into the functionality of popular libraries to automatically instrument your application and give you the best data out of the box.
+
+Integrations automatically add error instrumentation, performance instrumentation, and/or extra context information to your application. Some are enabled by default, but you can disable them or modify their settings. Others can be added to extend the default functionality of the SDK.
+
+## Adding an Integration
+
+You can add additional integrations in your `init` call:
+
+```javascript
+import * as Sentry from "@sentry/react-native";
+
+Sentry.init({
+ dsn: "___PUBLIC_DSN___",
+ integrations: [Sentry.dedupeIntegration()],
+});
+```
+
+Alternatively, you can add integrations via `Sentry.addIntegration()`.
+This is useful if you only want to enable an integration in a specific environment or if you want to load an integration later.
+For all other cases, we recommend you use the `integrations` option.
+
+```javascript
+import * as Sentry from "@sentry/react-native";
+
+Sentry.init({
+ integrations: [],
+});
+
+Sentry.addIntegration(Sentry.dedupeIntegration());
+```
+
+### HttpClient
+
+_(New in version 5.3.0)_
+
+_Import name: `Sentry.httpContextIntegration`_
+
+This integration captures errors on failed requests from Fetch and XHR and attaches request and response information.
+
+By default, error events don't contain header or cookie data. You can change this behavior by setting the `sendDefaultPii` option to `true`.
+
+```javascript {tabTitle:npm}
+import * as Sentry from "@sentry/react-native";
+
+Sentry.init({
+ dsn: "___PUBLIC_DSN___",
+ integrations: [Sentry.httpClientIntegration()]
+
+ // This option is required for capturing headers and cookies.
+ sendDefaultPii: true,
+});
+```
+
+
+
+Due to the limitations of both the Fetch and XHR API, the cookie and header collection for both requests and responses is based on best effort. Certain headers may be missing in the event created by the integration.
+
+
+
+### RewriteFrames
+
+_Import name: `Sentry.rewriteFramesIntegration`_
+
+This integration allows you to apply a transformation to each frame of the stack trace. In the streamlined scenario, it can be used to change the name of the file frame it originates from, or it can be fed with an iterated function to apply any arbitrary transformation.
+
+On Windows machines, you have to use Unix paths and skip the volume letter in the `root` option to enable it. For example, `C:\\Program Files\\Apache\\www` won’t work, however, `/Program Files/Apache/www` will.
+
+```javascript
+import * as Sentry from "@sentry/react-native";
+
+Sentry.init({
+ dsn: "___PUBLIC_DSN___",
+ integrations: [Sentry.rewriteFramesIntegration(
+ {
+ // root path that will be stripped from the current frame's filename by the default iteratee if the filename is an absolute path
+ root: string;
+
+ // a custom prefix that will be used by the default iteratee (default: `app://`)
+ prefix: string;
+
+ // function that takes the frame, applies a transformation, and returns it
+ iteratee: (frame) => frame;
+ }
+ )],
+});
+```
+
+#### Usage Examples
+
+We'll use `bundles/bundle1.js` as an example full path to your file for the table below:
+
+| Usage | Path in Stack Trace | Description |
+| -------------------------------------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
+| `RewriteFrames()` | `app:///bundle1.js` | The default behavior is to replace the absolute path, minus the filename, and add the default prefix (`app:///`). |
+| `RewriteFrames({root: '/bundles'})` | `app:///bundle1.js` | The `root` is defined as `/bundles`. Only that part is trimmed from the beginning of the path. |
+| `RewriteFrames({iteratee: () => {} })` | `app:///bundle.js` | The number at the end of a bundle can be a file hash. This is common in Expo apps. You can remove it in the `iteratee` callback. |
diff --git a/docs/platforms/react-native/profiling/index.mdx b/docs/platforms/react-native/profiling/index.mdx
index 8ef5b3f30e759..336f6d7fcb242 100644
--- a/docs/platforms/react-native/profiling/index.mdx
+++ b/docs/platforms/react-native/profiling/index.mdx
@@ -4,7 +4,6 @@ description: "Learn how to enable profiling in your app if it is not already set
sidebar_order: 5000
---
-
## Enable Tracing
@@ -14,6 +13,8 @@ Profiling depends on Sentry’s Tracing product being enabled beforehand. To ena
```javascript
Sentry.init({
dsn: "___DSN___",
+ // Set tracesSampleRate to 1.0 to capture 100% of transactions for tracing.
+ // We recommend adjusting this value in production.
tracesSampleRate: 1.0,
});
```
@@ -24,7 +25,7 @@ Check out the tracing setup documentation
-Profiling for React Native is available in beta in SDK versions `5.8.0` and above.
+Profiling for React Native is available in SDK versions `5.32.0` and above.
@@ -33,11 +34,11 @@ To enable profiling, set the `profilesSampleRate`:
```javascript
Sentry.init({
dsn: "___DSN___",
+ // Set tracesSampleRate to 1.0 to capture 100% of transactions for tracing.
+ // We recommend adjusting this value in production.
tracesSampleRate: 1.0,
- _experiments: {
- // profilesSampleRate is relative to tracesSampleRate.
- // Here, we'll capture profiles for 100% of transactions.
- profilesSampleRate: 1.0,
- },
+ // profilesSampleRate is relative to tracesSampleRate.
+ // Here, we'll capture profiles for 100% of transactions.
+ profilesSampleRate: 1.0,
});
```
diff --git a/docs/platforms/react-native/tracing/index.mdx b/docs/platforms/react-native/tracing/index.mdx
index 2f2fbb58770ed..42a3e094c2c4a 100644
--- a/docs/platforms/react-native/tracing/index.mdx
+++ b/docs/platforms/react-native/tracing/index.mdx
@@ -6,10 +6,6 @@ sidebar_order: 4000
With [tracing](/product/performance/), Sentry tracks your software performance, measuring metrics like throughput and latency, and displaying the impact of errors across multiple systems. Sentry captures distributed traces consisting of transactions and spans, which measure individual services and individual operations within those services. Learn more about our model in [Distributed Tracing](/product/sentry-basics/tracing/distributed-tracing/).
-## Enable Tracing
-
-
-
## Configure
First, enable tracing and configure the sample rate for transactions. Set the sample rate for your transactions by either:
diff --git a/docs/platforms/react-native/tracing/instrumentation/automatic-instrumentation.mdx b/docs/platforms/react-native/tracing/instrumentation/automatic-instrumentation.mdx
index 3d4b21c104f45..90c9f97b1856c 100644
--- a/docs/platforms/react-native/tracing/instrumentation/automatic-instrumentation.mdx
+++ b/docs/platforms/react-native/tracing/instrumentation/automatic-instrumentation.mdx
@@ -28,13 +28,14 @@ When no routing instrumentation is used, a transaction for `App Start` is automa
We currently provide three routing instrumentations out of the box to instrument route changes for:
+- [Expo Router](/platforms/react-native/tracing/instrumentation/expo-router/)
- [React Navigation](/platforms/react-native/tracing/instrumentation/react-navigation/)
-- [React Navigation V4 and prior](/platforms/react-native/tracing/instrumentation/react-navigation-v4/)
- [React Native Navigation](/platforms/react-native/tracing/instrumentation/react-native-navigation/)
-- [Expo Router](/platforms/react-native/tracing/instrumentation/expo-router/)
-- [Custom Instrumentation](/platforms/react-native/tracing/instrumentation/custom-navigation/), implement automatic navigation instrumentation for a custom library.
-If you have a custom routing instrumentation or use a routing library we don't yet support, you can use the [bare bones routing instrumentation](#bare-bones) or [create your own](#custom-instrumentation) by extending it.
+### Additional Instrumentation
+
+- [Custom Navigation](/platforms/react-native/tracing/instrumentation/custom-navigation/) to add the custom navigation library integration
+- [Custom Instrumentation](/platforms/react-native/tracing/instrumentation/custom-navigation/) to add custom performance data to your application
## Features
@@ -52,12 +53,6 @@ If you don't [wrap your root component with Sentry](#wrap-your-root-component),
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`.
-
-
-For SDKs from version `4.4.0` to `5.0.0` the app start measurements are available under `measurements.app.start.warm` and `measurements.app.start.cold` as custom measurements.
-
-
-
Cold and warm start are Mobile Vitals, which you can learn about in the [full documentation](/product/insights/mobile-vitals).
### Slow and Frozen Frames
@@ -111,90 +106,72 @@ import * as Sentry from "@sentry/react-native";
Sentry.init({
dsn: "___PUBLIC_DSN___",
- integrations: [new Sentry.ReactNativeTracing()],
+ integrations: [Sentry.reactNativeTracingIntegration()],
});
```
-For all possible options, see [ReactNativeTracingOptions](https://github.com/getsentry/sentry-react-native/blob/211ec081b6bf8d7d29541afe9d800040f61e3c4e/src/js/tracing/reactnativetracing.ts#L23).
+### tracePropagationTargets
+
+The default value of `tracePropagationTargets` is `['localhost', /^\//]`. The React Native 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.**
+
+
-### beforeNavigate
+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.
-You can use `beforeNavigate` to modify the transaction from routing instrumentation before the transaction is created. If you prefer not to send the transaction, set `sampled = false`.
+### 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: [
- new Sentry.ReactNativeTracing({
- routingInstrumentation,
- beforeNavigate: (context) => {
- // Decide to not send a transaction by setting sampled = false
- if (context.data.route.name === "Do Not Send") {
- context.sampled = false;
- }
-
- // Modify the transaction context
- context.name = context.name.toUpperCase();
- context.tags = {
- ...context.tags,
- customTag: "value",
+ Sentry.reactNativeTracingIntegration({
+ beforeStartSpan: (context) => {
+ return {
+ ...context,
+ attributes: {
+ ...context.attributes,
+ "custom": "value",
+ },
};
-
- return context;
},
}),
],
});
```
-If you use our routing instrumentation for **React Navigation**, the route data is set on the transaction context passed to `beforeNavigate`. This has the type:
+### 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.
-```typescript
-type ReactNavigationTransactionContext = {
+```javascript
+Sentry.init({
// ...
- data: {
- route: {
- name: string;
- key: string;
- params: {
- [key: string]: any;
- };
- /** Will be true if this is not the first time this screen with this key has been seen before. */
- hasBeenSeen: boolean;
- };
- previousRoute: {
- name: string;
- key: string;
- params: {
- [key: string]: any;
- };
- } | null;
- };
-};
+ integrations: [
+ Sentry.reactNativeTracingIntegration({
+ shouldCreateSpanForRequest: (url) => {
+ // Do not create spans for outgoing requests to a `/health/` endpoint
+ return !url.match(/\/health\/?$/);
+ },
+ }),
+ ],
+});
```
-If you use **Typescript**, you can type your `beforeNavigate` function with `Sentry.ReactNavigationTransactionContext`.
-
-### tracePropagationTargets
-
-The default value of `tracePropagationTargets` is `['localhost', /^\//]`. The React Native 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 will 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 do not unnecessarily have the `sentry-trace` header attached.**
-
-
-
-You will 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 do not allow the `sentry-trace` header, the request might be blocked.
-
-### shouldCreateSpanForRequest
+### idleTimeoutMs
-This function can be used to filter out unwanted spans, such as XHR's running health checks or something similar. By default, `shouldCreateSpanForRequest` already filters out everything except what was defined in `tracePropagationTargets`.
+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`.
-### maxTransactionDuration
+### finalTimeoutMs
-The maximum duration of a transaction, measured in seconds, before it will be marked as "deadline_exceeded". If you never want transactions marked that way, set `maxTransactionDuration` to 0.
+The maximum duration of the transaction, measured in ms. If the transaction duration hits the `finalTimeout` value, it will be done.
-The default is `600`.
+The default is `60_0000`.
## Recipes
diff --git a/docs/platforms/react-native/tracing/instrumentation/custom-instrumentation.mdx b/docs/platforms/react-native/tracing/instrumentation/custom-instrumentation.mdx
index 4f9bf0322b705..9ccca08a22c6a 100644
--- a/docs/platforms/react-native/tracing/instrumentation/custom-instrumentation.mdx
+++ b/docs/platforms/react-native/tracing/instrumentation/custom-instrumentation.mdx
@@ -14,34 +14,228 @@ To add custom performance data to your application, you need to add custom instr
To get started, import the SDK.
-
+```javascript
+import * as Sentry from "@sentry/react-native";
+```
-
+There are three key functions for creating spans:
-## Start Span
+- [startSpan](#starting-an-active-span-startspan): Creates a new span that is active and ends automatically. You'll likely want to use this function.
+- [startSpanManual](#starting-an-active-span-with-manual-end-startspanmanual): Creates a new span that is active and has to be ended manually.
+- [startInactiveSpan](#starting-inactive-spans-startinactivespan): Creates a new span that is inactive and has to be ended manually.
-By default, spans you create are considered active, which means they are put on the Sentry scope. This allows child spans and Sentry errors to be associated with that span. This is the recommended way to create spans.
+## Active vs. Inactive Spans
+
+If there's a currently active span when a new span is started, the new span will automatically start as a child span of the currently active one. This means, that if a span is started as an **active span**, it will be the parent span and any spans created inside the callback will be children of that span. Errors will be tied to the parent span, if there is one.
+
+In contrast, **inactive spans** will never have children automatically associated with them. This is useful if you don't care about capturing child activity.
+
+A key constraint for active spans is that they can only be made active inside of a callback. This constraint exists because otherwise it would be impossible to associate child spans with the correct parent span when working with asynchronous code.
+
+If you're unable to wrap executing code in a callback (for example, when working with hooks or similar) you'll have to work with inactive spans, and can combine this with [withActiveSpan](#withactivespan) to manually associate child spans with the correct parent span.
+
+## Span Hierarchy
+
+In browser and mobile environments, spans are collected in a flat hierarchy where every span is the direct child of the root span by default.
+
+The key reason for keeping a flat hierarchy is because if multiple asynchronous operations were started in parallel, it wouldn't be possible to determine which span is the parent of which child span. Imagine the following example:
+
+```javascript
+Sentry.startSpan({ name: "span 1" }, async () => {
+ await fetch("https://example.com/1");
+ await fetch("https://example.com/2");
+ await fetch("https://example.com/3");
+});
+
+Sentry.startSpan({ name: "span 2" }, async () => {
+ await fetch("https://example.com/4");
+ await fetch("https://example.com/5");
+ await fetch("https://example.com/6");
+});
+```
+
+In the browser, there would be no way to know that `span 1` is only active inside of its callback, while `span 2` is active in the other callback. Without a flat hierarchy, _all_ fetch spans would become children of `span 2`. This would be misleading and confusing, which is why we've made it so that in the browser, **all spans become children of the root span** (which is usually the pageload or navigation span) by default. This makes it so that you'll always have a flat hierarchy of spans.
+
+This is a tradeoff we've made to ensure that the data that's captured is accurate and reliable. If you need to capture a more complex hierarchy of spans, you can opt out of this behavior by setting `parentSpanIsAlwaysRootSpan: false`:
+
+```javascript
+Sentry.init({
+ parentSpanIsAlwaysRootSpan: false,
+});
+```
+
+If you choose to revert to using full hierarchy behavior where spans are children of the currently active span, you'll have to make sure there are no multiple parallel asynchronous operations that start spans. Otherwise, you may get incorrect data.
+
+## Span Starting Options
+
+The following options can be used for all span starting functions:
+
+| Option | Type | Description |
+| ------------------ | --------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
+| `name` | `string` | The name of the span. |
+| `op` | `string` | The operation of the span. |
+| `startTime` | `number` | The start time of the span. |
+| `attributes` | `Record` | Attributes to attach to the span. |
+| `parentSpan` | `Span` | If set, makes the span a child of the specified span. Otherwise, the span will be a child of the currently active span. |
+| `onlyIfParent` | `boolean` | If true, ignores the span if there's no active parent span. |
+| `forceTransaction` | `boolean` | If true, ensures this span shows up as a transaction in the Sentry UI. |
+
+The only option that's required is `name`. All other options are optional.
+
+## Starting an Active Span (`startSpan`)
+
+For most scenarios, we recommend to start active spans with `Sentry.startSpan()`. This will start a new span that is active in the provided callback, and will automatically end the span when the callback is done. The callback can be synchronous, or asynchronous (a promise). In the case of an asynchronous callback, the span will be ended when the promise is resolved or rejected. If the provided callback errors or rejects, the span will be marked as failed.
-## Start Inactive Spans
+## Starting an Active Span with Manual End (`startSpanManual`)
+
+There are times when you don't want a span to be ended automatically as soon as the callback is done. In this case, you can use `Sentry.startSpanManual()`. This will start a new active span in the provided callback, but it won't be automatically ended when the callback is done. You'll have to manually end the span by calling `span.end()`.
+
+
-To add spans that aren't active, you can create independent spans. This is useful for when you have work that is grouped together under a single parent span, but is independent from the current active span. However, in most cases you'll want to create and use the start span API from above.
+## Starting Inactive Spans (`startInactiveSpan`)
+
+To add spans that aren't active, you can create independent spans. This is useful when you have work that's grouped together under a single parent span, but is independent from the currently active span. However, in most cases you'll want to create and use the [startSpan](#starting-an-active-span-startspan) API from above.
-## Adding Span operations
+## Starting Spans as Children of a Specific Span
+
+By default, any span that's started will be the child of the currently active span. If you want to have a different behavior, you can force spans to be the children of a specific span with the `parentSpan` option:
+
+```js
+const parentSpan = Sentry.startInactiveSpan({ name: "Parent Span" });
+const childSpan = Sentry.startInactiveSpan({ name: "Child Span", parentSpan });
+
+childSpan.end();
+parentSpan.end();
+```
+
+This option is also available for `startSpan` and `startSpanManual`.
+
+## Utilities That Work With Spans
-Spans can have an operation associated with them, which help activate Sentry identify additional context about the span. For example database related spans have the `db` span operation associated with them. The Sentry product offers additional controls, visualizations and filters for spans with known operations.
+We expose some helpful utilities that can help you with custom instrumentation.
+
+### `getActiveSpan`
+
+Returns the currently active span.
+
+```javascript
+const activeSpan = Sentry.getActiveSpan();
+```
+
+### `getRootSpan`
+
+Returns the root span of a given span. If the span is already the root span, it will return the span itself.
+
+```javascript
+const activeSpan = Sentry.getActiveSpan();
+const rootSpan = activeSpan ? Sentry.getRootSpan(activeSpan) : undefined;
+```
+
+### `withActiveSpan`
+
+This method allows you to make a span active for the duration of a callback. You can use this in combination with `startInactiveSpan` to manually associate child spans with the correct parent span:
+
+```javascript
+const span = Sentry.startInactiveSpan({ name: "Parent Span" });
+
+Sentry.withActiveSpan(span, () => {
+ // `span` is now active, any other spans will be children of it
+ Sentry.startSpan({ name: "Child Span" }, () => {
+ // Do something
+ });
+});
+```
+
+You can also pass `null` to `withActiveSpan` to ensure a span will not have any parent:
+
+```javascript
+Sentry.withActiveSpan(null, () => {
+ // This will not have a parent span, no matter what
+ Sentry.startSpan({ name: "Parent Span" }, () => {
+ // Do something
+ });
+});
+```
+
+Alternatively, you can use the `parentSpan` option to achieve the same:
+
+```javascript
+const span = Sentry.startInactiveSpan({ name: "Parent Span" });
+const childSpan = Sentry.startInactiveSpan({
+ name: "Child Span",
+ parentSpan: span,
+});
+```
+
+### `suppressTracing`
+
+Suppress the creation of sampled spans for the duration of the callback. This is useful when you want to prevent certain spans from being captured. For example, if you don't want to create spans for a given fetch request, you can do:
+
+```javascript
+Sentry.suppressTracing(() => {
+ fetch("https://example.com");
+});
+```
+
+## Improving Span Data
+
+### Adding Span Attributes
+
+You can capture span attributes along with your spans. Span attributes can be of type: `string`, `number`, or `boolean`, as well as (non-mixed) arrays of these types. You can specify attributes when starting a span:
+
+```javascript
+Sentry.startSpan(
+ {
+ attributes: {
+ attr1: "value1",
+ attr2: 42,
+ attr3: true,
+ },
+ },
+ () => {
+ // Do something
+ }
+);
+```
+
+You can also add attributes to an existing span:
+
+```javascript
+const span = Sentry.getActiveSpan();
+if (span) {
+ span.setAttribute("attr1", "value1");
+ // Or set multiple attributes at once:
+ span.setAttributes({
+ attr2: 42,
+ attr3: true,
+ });
+}
+```
+
+### Adding Span Operations ("op")
+
+Spans can have an operation associated with them, which help activate Sentry and identify additional context about the span. For example, database-related spans have the `db` span operation associated with them. The Sentry product offers additional controls, visualizations, and filters for spans with known operations.
Sentry maintains a [list of well known span operations](https://develop.sentry.dev/sdk/performance/span-operations/#list-of-operations) and it is recommended that you use one of those operations if it is applicable to your span.
-## Start Transaction
+### Updating the Span Name
+
+You can update the name of a span at any time:
-The root span (the span that is the parent of all other spans) is known as a **transaction** in Sentry. Transactions can be accessed and created separately if you need more control over your timing data or if you use a version of the SDK that doesn't support the top-level span APIs.
+```javascript
+const span = Sentry.getActiveSpan();
+if (span) {
+ span.updateName("New Name");
+}
+```
-
+Please note, that in certain scenarios, the span name will be overwritten by the SDK. This is the case for spans with any of the following attribute combinations:
-
+* Spans with `http.method` or `http.request.method` attributes will automatically have their name set to the method + the URL path
+* Spans with `db.system` attributes will automatically have their name set to the system + the statement
diff --git a/docs/platforms/react-native/tracing/instrumentation/custom-navigation.mdx b/docs/platforms/react-native/tracing/instrumentation/custom-navigation.mdx
index bab1f87e41f6c..0bd8bea2ce524 100644
--- a/docs/platforms/react-native/tracing/instrumentation/custom-navigation.mdx
+++ b/docs/platforms/react-native/tracing/instrumentation/custom-navigation.mdx
@@ -4,64 +4,33 @@ description: "Learn how to use Sentry's Generic Navigation instrumentation."
sidebar_order: 70
---
-Sentry's React Native SDK package ships with instrumentation for [React Navigation](/platforms/react-native/tracing/instrumentation/react-navigation/) and [React Native Navigation](/platforms/react-native/tracing/instrumentation/react-native-navigation/). This allows you to see the performance of your navigation transitions and the errors that occur during them.
+Sentry's React Native SDK package ships with instrumentation for [React Navigation](/platforms/react-native/tracing/instrumentation/react-navigation/), [React Native Navigation](/platforms/react-native/tracing/instrumentation/react-native-navigation/), and [Expo Router](/platforms/react-native/tracing/instrumentation/expo-router/). This allows you to see the performance of your navigation transitions and the errors that may occur.
-If you use a navigation library that we don't yet support, or have a custom routing solution, you can use the basic `RoutingInstrumentation`. This page will guide you through setting it up and configuring it to your needs.
+If you use a navigation library that we don't yet support, or have a custom routing solution, you can use `startIdleNavigationSpan` function to implement your own navigation integration. This page will guide you through setting it up and configuring it to your needs.
-## Bare Bones
+```javascript {filename: customNavigationIntegration.js}
+import Sentry from '@sentry/react-native';
-Every routing instrumentation revolves around one method:
-
-`onRouteWillChange` (context: TransactionContext): Transaction | undefined
-
-You need to ensure that this method is called **before** the route change occurs, and an `IdleTransaction` is created and set on the scope.
+const customNavigationIntegration = ({navigator}) => {
+ navigator.registerRouteChangeListener((newRoute) => {
+ Sentry.startIdleNavigationSpan({
+ name: newRoute.name,
+ op: 'navigation'
+ })
+ });
-```javascript
-// Construct a new instrumentation instance. This is needed to communicate between the integration and React
-const routingInstrumentation = new Sentry.RoutingInstrumentation();
+ return {
+ name: "CustomNavigation",
+ };
+};
Sentry.init({
- ...
- integrations: [
- new Sentry.ReactNativeTracing({
- // Pass instrumentation to be used as `routingInstrumentation`
- routingInstrumentation,
- ...
- }),
- ],
-})
-
-const App = () => {
- {
- // Call this before the route changes
- routingInstrumentation.onRouteWillChange({
- name: newRoute.name,
- op: 'navigation'
- })
- }}
- />
-};
+ dsn: '___PUBLIC_DSN___',
+ // Set tracesSampleRate to 1.0 to capture 100% of transactions for tracing.
+ // We recommend adjusting this value in production.
+ tracesSampleRate: 1.0,
+ integrations: [customNavigationIntegration({navigator})],
+});
```
-## Custom Instrumentation
-
-To create a custom routing instrumentation, look at how the `RoutingInstrumentation` class [is implemented](https://github.com/getsentry/sentry-react-native/blob/211ec081b6bf8d7d29541afe9d800040f61e3c4e/src/js/tracing/routingInstrumentation.ts). If you need an example of how to implement routing instrumentation, review the code of the existing official instrumentation such as [the one for React Navigation V4](https://github.com/getsentry/sentry-react-native/blob/211ec081b6bf8d7d29541afe9d800040f61e3c4e/src/js/tracing/reactnavigationv4.ts)
-
-```javascript
-class CustomInstrumentation extends RoutingInstrumentation {
- constructor(navigator) {
- super();
-
- this.navigator.registerRouteChangeListener(this.routeListener.bind(this));
- }
-
- routeListener(newRoute) {
- // Again, ensure this is called BEFORE the route changes and BEFORE the route is mounted.
- this.onRouteWillChange({
- name: newRoute.name,
- op: "navigation",
- });
- }
-}
-```
+To lear more about the `Integration` lifecycle, see the [Integration API](/platforms/react-native/integrations/custom/).
diff --git a/docs/platforms/react-native/tracing/instrumentation/expo-router.mdx b/docs/platforms/react-native/tracing/instrumentation/expo-router.mdx
index a7b6b39570282..0ebc3930ddfa4 100644
--- a/docs/platforms/react-native/tracing/instrumentation/expo-router.mdx
+++ b/docs/platforms/react-native/tracing/instrumentation/expo-router.mdx
@@ -10,32 +10,30 @@ Sentry's React Native SDK package ships with instrumentation for Expo Router. Th
The code snippet below shows how to initialize the instrumentation.
-```javascript { filename: 'app/_layout.tsx' }
+```javascript {6-8, 15-16, 20-25} {filename: app/_layout.tsx}
import React from 'react';
import { Slot, useNavigationContainerRef } from 'expo-router';
-import Constants from 'expo-constants';
+import Constants, { ExecutionEnvironment.StoreClient } from 'expo-constants';
import * as Sentry from '@sentry/react-native';
-const routingInstrumentation = new Sentry.ReactNavigationInstrumentation({
- enableTimeToInitialDisplay: Constants.appOwnership !== 'expo', // Only in native builds, not in Expo Go.
+const navigationIntegration = Sentry.reactNavigationintegration({
+ enableTimeToInitialDisplay: Constants.executionEnvironment === ExecutionEnvironment.StoreClient, // Only in native builds, not in Expo Go.
});
Sentry.init({
dsn: '___PUBLIC_DSN___',
- integrations: [
- new Sentry.ReactNativeTracing({
- routingInstrumentation,
- enableNativeFramesTracking: Constants.appOwnership !== 'expo', // Only in native builds, not in Expo Go.
- }),
- ],
+ // Set tracesSampleRate to 1.0 to capture 100% of transactions for tracing.
+ // We recommend adjusting this value in production.
+ tracesSampleRate: 1.0,
+ integrations: [navigationIntegration],
+ enableNativeFramesTracking: Constants.executionEnvironment === ExecutionEnvironment.StoreClient, // Only in native builds, not in Expo Go.
});
function RootLayout() {
const ref = useNavigationContainerRef();
-
React.useEffect(() => {
if (ref) {
- routingInstrumentation.registerNavigationContainer(ref);
+ navigationIntegration.registerNavigationContainer(ref);
}
}, [ref]);
@@ -50,19 +48,24 @@ export default Sentry.wrap(RootLayout);
You can configure the instrumentation by passing an options object to the constructor:
```javascript
-new Sentry.ReactNavigationInstrumentation({
+Sentry.reactNavigationintegration({
enableTimeToInitialDisplay: true, // default: false
routeChangeTimeoutMs: 1000, // default: 1000
+ ignoreEmptyBackNavigationTransactions: true, // default: true
});
```
### routeChangeTimeoutMs
-This option specifies how long the instrumentation will wait for the route to mount after a change has been initiated before the transaction is discarded. The default value is 1000ms.
+This option specifies how long the instrumentation will wait for the route to mount after a change has been initiated before the transaction is discarded. The default value is `1_000`.
### enableTimeToInitialDisplay
-This option will enable automatic measuring of the time to initial display for each route. To learn more see [Time to Initial Display](/platforms/react-native/tracing/instrumentation/time-to-display).
+This option will enable automatic measuring of the time to initial display for each route. To learn more see [Time to Initial Display](/platforms/react-native/tracing/instrumentation/time-to-display). The default value is `false`.
+
+### ignoreEmptyBackNavigationTransactions
+
+This ensures that transactions that are from routes that've been seen and don't have any spans, are not being sampled. This removes a lot of clutter, making it so that most back navigation transactions are now ignored. The default value is `true`.
## Notes
diff --git a/docs/platforms/react-native/tracing/instrumentation/react-native-navigation.mdx b/docs/platforms/react-native/tracing/instrumentation/react-native-navigation.mdx
index 828ac90bd4c5c..7d12eb8409416 100644
--- a/docs/platforms/react-native/tracing/instrumentation/react-native-navigation.mdx
+++ b/docs/platforms/react-native/tracing/instrumentation/react-native-navigation.mdx
@@ -10,19 +10,15 @@ Sentry's React Native SDK package ships with instrumentation for [React Native N
You will need to pass the `Navigation` object imported from the library to initialize our routing instrumentation. It is recommended that you initialize our SDK and the routing instrumentation as early as possible in the lifecycle of your app; this would most likely be before the point where you initialize your screens.
-```javascript {filename: index.js}
+```javascript {7-9} {filename: index.js}
import * as Sentry from "@sentry/react-native";
import { Navigation } from 'react-native-navigation';
Sentry.init({
- ...
+ dsn: "___PUBLIC_DSN___",
integrations: [
- new Sentry.ReactNativeTracing({
- // Pass instrumentation to be used as `routingInstrumentation`
- routingInstrumentation: new Sentry.ReactNativeNavigationInstrumentation(
- Navigation,
- )
- // ...
+ Sentry.reactNativeNavigationIntegration({
+ navigation: Navigation,
}),
],
})
@@ -33,11 +29,26 @@ Sentry.init({
You can configure the instrumentation by passing an options object to the constructor:
```javascript
-new Sentry.ReactNativeNavigationInstrumentation({
- routeChangeTimeoutMs: 1000, // default: 1000
+Sentry.reactNativeNavigationIntegration({
+ navigation: Navigation, // Navigation from `react-native-navigation`
+ routeChangeTimeoutMs: 1_000, // default: 1_000
+ enableTabsInstrumentation: true, // default: false
+ ignoreEmptyBackNavigationTransactions: true, // default: true
});
```
+### navigation
+
+This option is required and should be the `Navigation` object imported from the navigation library.
+
### routeChangeTimeoutMs
-This option specifies how long the instrumentation will wait for the route to mount after a change has been initiated before the transaction is discarded. The default value is 1000ms.
+This option specifies how long the instrumentation will wait for the route to mount after a change has been initiated before the transaction is discarded. The default value is `1_000`.
+
+### enableTabsInstrumentation
+
+This instrumentation will create a transaction on tab change. By default, only navigation commands create transactions. The default value is `false`.
+
+### ignoreEmptyBackNavigationTransactions
+
+This ensures that transactions that are from routes that've been seen and don't have any spans, are not being sampled. This removes a lot of clutter, making it so that most back navigation transactions are now ignored. The default value is `true`.
diff --git a/docs/platforms/react-native/tracing/instrumentation/react-navigation-v4.mdx b/docs/platforms/react-native/tracing/instrumentation/react-navigation-v4.mdx
deleted file mode 100644
index 7507a8f4849d5..0000000000000
--- a/docs/platforms/react-native/tracing/instrumentation/react-navigation-v4.mdx
+++ /dev/null
@@ -1,96 +0,0 @@
----
-title: React Navigation V4
-description: "Learn how to use Sentry's React Navigation Legacy instrumentation."
-sidebar_order: 51
----
-
-Sentry's React Native SDK package ships with instrumentation for React Navigation V4 and older. This allows you to see the performance of your navigation transitions and the errors that occur during them. This page will guide you through setting up the instrumentation and configuring it to your needs.
-
-## Initialization
-
-The code snippet below shows how to initialize the instrumentation.
-
-```jsx {tabTitle: Functional Components}
-// Construct a new instrumentation instance. This is needed to communicate between the integration and React
-const routingInstrumentation = new Sentry.ReactNavigationV4Instrumentation();
-
-Sentry.init({
- ...
- integrations: [
- new Sentry.ReactNativeTracing({
- // Pass instrumentation to be used as `routingInstrumentation`
- routingInstrumentation,
- ...
- }),
- ],
-})
-
-// Functional Component Example
-const App = () => {
- // Create a ref for the navigation container
- const appContainer = React.useRef();
-
- // Register the navigation container with the instrumentation
- React.useEffect(() => {
- routingInstrumentation.registerAppContainer(appContainer);
- }, []);
-
- return (
- // Connect the ref to the navigation container
-
- );
-};
-```
-
-```jsx {tabTitle: Class Components}
-// Construct a new instrumentation instance. This is needed to communicate between the integration and React
-const routingInstrumentation = new Sentry.ReactNavigationV4Instrumentation();
-
-Sentry.init({
- ...
- integrations: [
- new Sentry.ReactNativeTracing({
- // Pass instrumentation to be used as `routingInstrumentation`
- routingInstrumentation,
- ...
- }),
- ],
-})
-
-class App extends React.Component {
- // Create a ref for the navigation container
- appContainer = React.createRef();
-
- componentDidMount() {
- // Register the navigation container with the instrumentation
- routingInstrumentation.registerAppContainer(this.appContainer);
- }
-
- render() {
- return (
- // Connect the ref to the navigation container
-
- )
- }
-}
-```
-
-## Options
-
-You can configure the instrumentation by passing an options object to the constructor:
-
-```javascript
-new Sentry.ReactNavigationV4Instrumentation({
- routeChangeTimeoutMs: 1000, // default: 1000
-});
-```
-
-### routeChangeTimeoutMs
-
-This option specifies how long the instrumentation will wait for the **initial** route to mount after a change has been initiated before the transaction is discarded. The default value is 1000ms.
-
-## Notes
-
-- This instrumentation supports React Navigation version 4 and older. If you use React Navigation version 5 and newer, see the [instrumentation for React Navigation](/platforms/react-native/tracing/instrumentation/react-navigation/).
-
-- The instrumentation creates a transaction on every route change including `goBack` navigations.
diff --git a/docs/platforms/react-native/tracing/instrumentation/react-navigation.mdx b/docs/platforms/react-native/tracing/instrumentation/react-navigation.mdx
index 4bc800fb538e2..a5aa1b759f797 100644
--- a/docs/platforms/react-native/tracing/instrumentation/react-navigation.mdx
+++ b/docs/platforms/react-native/tracing/instrumentation/react-navigation.mdx
@@ -17,23 +17,28 @@ The code snippet below shows how to initialize the instrumentation.
You can configure the instrumentation by passing an options object to the constructor:
```javascript
-new Sentry.ReactNavigationInstrumentation({
+Sentry.reactNavigationintegration({
enableTimeToInitialDisplay: true, // default: false
- routeChangeTimeoutMs: 1000, // default: 1000
+ routeChangeTimeoutMs: 1_000, // default: 1_000
+ ignoreEmptyBackNavigationTransactions: true, // default: true
});
```
### routeChangeTimeoutMs
-This option specifies how long the instrumentation will wait for the route to mount after a change has been initiated before the transaction is discarded. The default value is 1000ms.
+This option specifies how long the instrumentation will wait for the route to mount after a change has been initiated before the transaction is discarded. The default value is `1_000`.
### enableTimeToInitialDisplay
-This option will enable automatic measuring of the time to initial display for each route. To learn more see [Time to Initial Display](/platforms/react-native/tracing/instrumentation/time-to-display).
+This option will enable automatic measuring of the time to initial display for each route. To learn more see [Time to Initial Display](/platforms/react-native/tracing/instrumentation/time-to-display). The default value is `false`.
+
+### ignoreEmptyBackNavigationTransactions
+
+This ensures that transactions that are from routes that've been seen and don't have any spans, are not being sampled. This removes a lot of clutter, making it so that most back navigation transactions are now ignored. The default value is `true`.
## Notes
-- This instrumentation supports React Navigation version 5 and above. If you use React Navigation version 4, see the [instrumentation for React Navigation V4](/platforms/react-native/tracing/instrumentation/react-navigation-v4/).
+- This instrumentation supports React Navigation version 5 and above. Starting with SDK version 6, React Navigation version 4 will no longer be supported. Please upgrade.
- The instrumentation creates a transaction on every route change including `goBack` navigations.
diff --git a/docs/platforms/react-native/tracing/instrumentation/time-to-display.mdx b/docs/platforms/react-native/tracing/instrumentation/time-to-display.mdx
index 7b00e8fbe4e84..980f1abacd58b 100644
--- a/docs/platforms/react-native/tracing/instrumentation/time-to-display.mdx
+++ b/docs/platforms/react-native/tracing/instrumentation/time-to-display.mdx
@@ -30,7 +30,7 @@ To automatically measure Time to Initial Display of React Navigation Screens, en
When the automatically captured Time to Initial Display doesn't meet your requirements, you can overwrite it by using `Sentry.TimeToInitialDisplay` component.
-```jsx {tabTitle: }
+```jsx {8} {tabTitle: }
import * as Sentry from "@sentry/react-native";
import * as React from "react";
import { View } from "react-native";
@@ -48,7 +48,7 @@ function MyComponent() {
To measure the time when a screen is fully displayed, you can use the `Sentry.TimeToFullDisplay` component.
-```jsx {tabTitle: }
+```jsx {17} {tabTitle: }
import * as Sentry from "@sentry/react-native";
import { useState, useEffect } from "react";
import { View, Text } from "react-native";
diff --git a/docs/platforms/react-native/tracing/instrumentation/user-interaction-instrumentation.mdx b/docs/platforms/react-native/tracing/instrumentation/user-interaction-instrumentation.mdx
index d33aa15002dca..fc8f890964841 100644
--- a/docs/platforms/react-native/tracing/instrumentation/user-interaction-instrumentation.mdx
+++ b/docs/platforms/react-native/tracing/instrumentation/user-interaction-instrumentation.mdx
@@ -20,18 +20,16 @@ Transaction names are composed from a combination of displayed screen names, (fo
UI instrumentation tracing is disabled by default, but you can enable it by setting the `enableUserInteractionTracing` options to `true` and wrapping your root component:
-```javascript
+```javascript {3-3, 7-9}
import * as Sentry from "@sentry/react-native";
+const navigationIntegration = Sentry.reactNavigationIntegration(); // Or any other navigation integration
+
Sentry.init({
- // ...
- integrations: [
- new Sentry.ReactNativeTracing({
- enableUserInteractionTracing: true,
- routingInstrumentation,
- // ...
- }),
- ],
+ dsn: "___PUBLIC_DSN___",
+ enableUserInteractionTracing: true,
+ tracesSampleRate: 1.0,
+ integrations: [navigationIntegration],
});
const App = () => Your App;
@@ -41,7 +39,7 @@ export default Sentry.wrap(App);
The label by which UI elements are identified is set by the `labelName` option in `Sentry.wrap`. If no value is supplied, `sentry-label` will be used instead. If an element can't be identified, the transaction won't be captured.
-```javascript
+```javascript {2-2}
export default Sentry.wrap(App, {
touchEventBoundaryProps: { labelName: "my-label" },
});
@@ -62,7 +60,7 @@ To create UI transactions from React Native Gesture Handler, you need to wrap in
Only [RNGH API v2](https://docs.swmansion.com/react-native-gesture-handler/docs/gestures/gesture/) is supported.
-```javascript
+```javascript {10-11}
import React from "react";
import { Gesture, GestureDetector } from "react-native-gesture-handler";
import { sentryTraceGesture } from "@sentry/react-native";
diff --git a/includes/platforms/configuration/integrations/plugin.mdx b/includes/platforms/configuration/integrations/plugin.mdx
deleted file mode 100644
index 6cf046797e988..0000000000000
--- a/includes/platforms/configuration/integrations/plugin.mdx
+++ /dev/null
@@ -1,134 +0,0 @@
-The below pluggable integrations are snippets of code that augment functionality for specific applications and/or frameworks. Read on to understand what they do and how to enable them.
-
-## How to Enable
-
-Install the `@sentry/integrations` package and provide a new instance with your config to the `integrations` option. Include the plugin after the SDK has been loaded.
-
-For example:
-
-
-
-Alternatively, you can add integrations lazily via `Sentry.addIntegration()`.
-This is useful if you only want to enable an integration in a specific environment or if you want to lazy-load an integration.
-For all other cases, we recommend you use the `integrations` option.
-
-
-
-
-
-
-
-### ExtraErrorData
-
-_Import name: `Sentry.Integrations.ExtraErrorData`_
-
-This integration extracts all non-native attributes from the `error` object and attaches them to the event as `extra` data. If the error object has a `.toJSON()` method, the `ExtraErrorData` integration will run it to extract additional information.
-
-Available options:
-
-
-
-
-
-### CaptureConsole
-
-_Import name: `Sentry.Integrations.CaptureConsole`_
-
-This integration captures all `Console API` calls and redirects them to Sentry using the SDK's `captureMessage` or `captureException` call, depending on the log level. It then re-triggers to preserve default native behavior.
-
-
-
-
-
-By default React [logs all errors to the console](https://github.com/facebook/react/blob/493f72b0a7111b601c16b8ad8bc2649d82c184a0/packages/react-reconciler/src/ReactFiberErrorLogger.js#L85), even if you are using an React error boundary. This means that Sentry will capture the error through the `CaptureConsole` integration and not through the error boundary. We recommend disabling logging the `error` level if using React error boundaries and the `CaptureConsole` integration.
-
-
-
-
-
-
-
-### Debug
-
-_Import name: `Sentry.Integrations.Debug`_
-
-This integration allows you to inspect the contents of a processed event and `hint` object that gets passed to `beforeSend` or `beforeSendTransaction`. It will _always_ run as the last integration, no matter when it was registered.
-
-Note that this is different than setting `debug: true` in your `Sentry.init` options, which will enable debug logging in the console.
-
-Available options:
-
-
-
-
-
-### HttpClient
-
-
-
-_(New in version 7.30.0)_
-
-
-
-
-
-_(New in version 5.3.0)_
-
-
-
-_Import name: `Sentry.Integrations.HttpClient`_
-
-This integration captures errors on failed requests from Fetch and XHR and attaches request and response information.
-
-By default, error events don't contain header or cookie data. You can change this behavior by setting the `sendDefaultPii` option to `true`.
-
-Available options:
-
-
-
-
-
-Due to the limitations of both the Fetch and XHR API, the cookie and header collection for both requests and responses is based on best effort. Certain headers may be missing in the event created by the integration.
-
-
-
-### RewriteFrames
-
-_Import name: `Sentry.Integrations.RewriteFrames`_
-
-This integration allows you to apply a transformation to each frame of the stack trace. In the streamlined scenario, it can be used to change the name of the file frame it originates from, or it can be fed with an iterated function to apply any arbitrary transformation.
-
-On Windows machines, you have to use Unix paths and skip the volume letter in the `root` option to enable it. For example, `C:\\Program Files\\Apache\\www` won’t work, however, `/Program Files/Apache/www` will.
-
-Available options:
-
-
-
-
-
-### ReportingObserver
-
-_Import name: `Sentry.Integrations.ReportingObserver`_
-
-This integration hooks into the ReportingObserver API and sends captured events through to Sentry. It can be configured to handle only specific issue types.
-
-Available options:
-
-
-
-
-
-
-
-### ContextLines
-
-_Import name: `Sentry.Integrations.ContextLines`_
-
-This integration adds source code from inline JavaScript of the current page's HTML (e.g. JS in `