xref: /expo/docs/pages/guides/using-sentry.mdx (revision dfd15ebd)
1---
2title: Using Sentry
3maxHeadingDepth: 4
4---
5
6import { ConfigReactNative, ConfigClassic } from '~/components/plugins/ConfigSection';
7import PlatformsSection from '~/components/plugins/PlatformsSection';
8import { Collapsible } from '~/ui/components/Collapsible';
9import { Terminal } from '~/ui/components/Snippet';
10import { Step } from '~/ui/components/Step';
11
12[Sentry](http://getsentry.com/) is a crash reporting platform that provides you with "real-time insight into production deployments with info to reproduce and fix crashes".
13
14It notifies you of exceptions or errors that your users run into while using your app, and organizes them for you on a web dashboard. Reported exceptions include stacktraces, device info, version, and other relevant context automatically; you can also provide additional context that is specific to your application, like the current route and user id.
15
16## Why sentry-expo?
17
18- Sentry treats React Native as a first-class citizen and we have collaborated with Sentry to make sure Expo is, too.
19- It's very easy to set up and use
20- It scales to meet the demands of even the largest projects.
21- We trust it for our projects at Expo.
22- It is free for up to 5,000 events per month.
23- It streamlines your error-reporting code across iOS, Android, and web
24
25> Native crash reporting is not available with the classic build system (`expo build:[ios|android]`), but is available via EAS Build.
26
27<PlatformsSection title="Platform compatibility" android emulator ios simulator web />
28
29## Installing and configuring Sentry
30
31### Step 1: Sign up for a Sentry account and create a project
32
33Before getting real-time updates on errors and making your app generally incredible, you'll need to make sure you've created a Sentry project. Here's how to do that:
34
35<Step label="1">
36  [Sign up for Sentry](https://sentry.io/signup/) (it's free), and create a project in your
37  Dashboard. Take note of your **organization name**, **project name**, and **`DSN`**; you'll need
38  them later. - **organization name** is available in your `Organization settings` tab - **project
39  name** is available in your project's `Settings` > `Projects` tab (find it in the list) -
40  **`DSN`** is available in your project's `Settings` > `Projects` > **Project name** > `Client Keys
41  (DSN)` tab
42</Step>
43
44<Step label="2">
45  Go to the [Sentry API section](https://sentry.io/settings/account/api/auth-tokens/), and create an
46  **auth token**. The token requires the scopes: `org:read`, `project:releases`, and
47  `project:write`. Save this, too.
48</Step>
49
50Once you have each of these: organization name, project name, DSN, and auth token, you're all set!
51
52### Step 2: Installation
53
54In your project directory, run:
55
56<Terminal cmd={['$ npx expo install sentry-expo']} />
57
58`sentry-expo` also requires some additional Expo module packages. To install them, run:
59
60<Terminal
61  cmd={[
62    '$ npx expo install expo-application expo-constants expo-device expo-updates @sentry/react-native',
63  ]}
64/>
65
66### Step 3: Code
67
68#### Initialization
69
70Add the following to your app's main file such as **App.js**:
71
72```js
73import * as Sentry from 'sentry-expo';
74
75Sentry.init({
76  dsn: 'YOUR DSN HERE',
77  enableInExpoDevelopment: true,
78  debug: true, // If `true`, Sentry will try to print out useful debugging information if something goes wrong with sending the event. Set it to `false` in production
79});
80```
81
82#### Usage
83
84Depending on which platform you are on (mobile or web), use the following methods to access any `@sentry/*` methods for instrumentation, performance, capturing exceptions and so on:
85
86- For React Native, access any `@sentry/react-native` exports with `Sentry.Native.*`
87- For web, access any `@sentry/browser` exports with `Sentry.Browser.*`
88
89```js
90// Access any @sentry/react-native exports via:
91// Sentry.Native.*
92
93// Access any @sentry/browser exports via:
94// Sentry.Browser.*
95
96// The following example uses `captureException()` from Sentry.Native.* to capture errors:
97try {
98  // your code
99} catch (error) {
100  Sentry.Native.captureException(error);
101}
102```
103
104### Step 4: App Configuration
105
106Configuring sentry-expo is done through the config plugin in your **app.json** or **app.config.js**.
107
108<ConfigClassic>
109
110The instructions below will still apply, with the exception of the `plugin` configuration. Config plugins have no effect when using the classic build system.
111
112</ConfigClassic>
113
114<ConfigReactNative>
115
116If you use bare workflow, **you should not use the `plugins` property in app.json**. Instead, use `yarn sentry-wizard -i reactNative -p ios android` to configure your native projects. This `sentry-wizard` command will add an extra:
117
118```js
119import * as Sentry from '@sentry/react-native';
120
121Sentry.init({
122  dsn: 'YOUR DSN',
123});
124```
125
126to your root project file (usually **App.js**), so make sure you remove it (but keep the `sentry-expo` import and original `Sentry.init` call!)
127
128</ConfigReactNative>
129
130#### Configure a `postPublish` hook
131
132Add `expo.hooks` to your project's `app.json` (or `app.config.js`) file:
133
134```json app.json
135{
136  "expo": {
137    /* @hide ... your existing configuration */ /* @end */
138    "hooks": {
139      "postPublish": [
140        {
141          "file": "sentry-expo/upload-sourcemaps",
142          "config": {
143            "organization": "your sentry organization slug here",
144            "project": "your sentry project name here",
145            "authToken": "your auth token here"
146          }
147        }
148      ]
149    }
150  }
151}
152```
153
154The `authToken` value can be generated from the [Sentry API page](https://sentry.io/settings/account/api/).
155
156<Collapsible summary="Prefer to use environment variables instead of storing values in app.json?">
157
158You can also use environment variables for your config, if you prefer:
159
160- organization → `SENTRY_ORG`
161- project → `SENTRY_PROJECT`
162- authToken → `SENTRY_AUTH_TOKEN`
163
164</Collapsible>
165
166<Collapsible summary="Additional configuration options">
167
168In addition to the required config fields above, you can also provide these **optional** fields:
169
170- `setCommits` : boolean value indicating whether or not to tell Sentry about which commits are associated with a new release. This allows Sentry to pinpoint which commits likely caused an issue.
171- `deployEnv` : string indicating the deploy environment. This will automatically send an email to Sentry users who have committed to the release that is being deployed.
172- `distribution` : The name/value to give your distribution (you can think of this as a sub-release). Expo defaults to using your `version` from app.json. **If you provide a custom `distribution`, you must pass the same value to `dist` in your call to `Sentry.init()`, otherwise you will not see stacktraces in your error reports.**
173- `release` : The name you'd like to give your release (e.g. `release-feature-ABC`). This defaults to a unique `revisionId` of your JS bundle. **If you provide a custom `release`, you must pass in the same `release` value to `Sentry.init()`, otherwise you will not see stacktraces in your error reports.**
174- `url` : your Sentry URL, only necessary when self-hosting Sentry.
175
176> You can also use environment variables for your config, if you prefer:
177>
178> - setCommits → `SENTRY_SET_COMMITS`
179> - deployEnv → `SENTRY_DEPLOY_ENV`
180> - distribution → `SENTRY_DIST`
181> - release → `SENTRY_RELEASE`
182> - url → `SENTRY_URL`
183
184</Collapsible>
185
186#### Add the Config Plugin
187
188Add `expo.plugins` to your project's `app.json` (or `app.config.js`) file:
189
190```json app.json
191{
192  "expo": {
193    /* @hide ... your existing configuration */ /* @end */
194    "plugins": ["sentry-expo"]
195  }
196}
197```
198
199## Sourcemaps
200
201{/* TODO: Drop `expo publish` mention */}
202
203With the `postPublish` hook in place, now all you need to do is run `expo publish` and the sourcemaps will be uploaded automatically. We automatically assign a unique release version for Sentry each time you hit publish, based on the version you specify in **app.json** and a release id on our backend -- this means that if you forget to update the version but hit publish, you will still get a unique Sentry release.
204
205> This hook can also be used as a `postExport` hook if you're [self-hosting your updates](../distribution/custom-updates-server.mdx).
206
207### Uploading sourcemaps at build time
208
209> Note: Disregard the following if you're using the classic build system (`expo build:[android|ios]`).
210
211With `expo-updates`, release builds of both iOS and Android apps will create and embed a new update from your JavaScript source at build-time. **This new update will not be published automatically** and will exist only in the binary with which it was bundled. Since it isn't published, the sourcemaps aren't uploaded in the usual way like they are when you run `expo publish` (actually, we are relying on Sentry's native scripts to handle that). Because of this you have some extra things to be aware of:
212
213- Your `release` will automatically be set to Sentry's expected value- `${bundleIdentifier}@${version}+${buildNumber}` (iOS) or `${androidPackage}@${version}+${versionCode}` (Android).
214- Your `dist` will automatically be set to Sentry's expected value: `${buildNumber}` (iOS) or `${versionCode}` (Android).
215- The configuration for build time sourcemaps comes from the `ios/sentry.properties` and `android/sentry.properties` files. For more information, refer to [Sentry's documentation](https://docs.sentry.io/clients/java/config/#configuration-via-properties-file). Manual configuration is only required for bare projects, the [sentry-expo config plugin handles it otherwise](#add-the-config-plugin).
216- Configuration for `expo publish` and `npx expo export` for projects is done via `app.json`, whether using bare workflow or not.
217
218Skipping or misconfiguring either of these can lead to invalid sourcemaps, and you won't see human-readable stacktraces in your errors.
219
220### Self-hosting updates
221
222If you're self-hosting your updates (this means you run `npx expo export` instead of `expo publish`), you need to:
223
224- replace `hooks.postPublish` in your **app.json** file with `hooks.postExport` (everything else stays the same)
225- add the `RewriteFrames` integration to your `Sentry.init` call like so:
226
227```js
228Sentry.init({
229  dsn: SENTRY_DSN,
230  enableInExpoDevelopment: true,
231  integrations: [
232    new RewriteFrames({
233      iteratee: frame => {
234        if (frame.filename) {
235          // the values depend on what names you give the bundle files you are uploading to Sentry
236          frame.filename =
237            Platform.OS === 'android' ? 'app:///index.android.bundle' : 'app:///main.jsbundle';
238        }
239        return frame;
240      },
241    }),
242  ],
243});
244```
245
246### Testing Sentry
247
248When building tests for your application, you want to assert that the right flow-tracking or error is being sent to Sentry, but without really sending it to Sentry servers. This way you won't swamp Sentry with false reports during test running and other CI operations.
249
250[`sentry-testkit`](https://wix.github.io/sentry-testkit) enables Sentry to work natively in your application, and by overriding the default Sentry transport mechanism, the report is not really sent but rather logged locally into memory. In this way, the logged reports can be fetched later for your own usage, verification, or any other use you may have in your local developing/testing environment.
251
252See how to get started with `sentry-testkit` in their [documentation site here](https://wix.github.io/sentry-testkit/)
253
254> If you're using `jest`, make sure to add `@sentry/.*` and `sentry-expo` to your `transformIgnorePatterns`.
255
256## Error reporting semantics
257
258In order to ensure that errors are reported reliably, Sentry defers reporting the data to their backend until the next time you load the app after a fatal error rather than trying to report it upon catching the exception. It saves the stacktrace and other metadata to `AsyncStorage` and sends it immediately when the app starts.
259
260## Disabled by default in dev
261
262Unless `enableInExpoDevelopment: true` is set, all your dev/local errors will be ignored and only app releases will report errors to Sentry. You can call methods like `Sentry.Native.captureException(new Error('Oops!'))` but these methods will be no-op.
263
264## Learn more about Sentry
265
266Sentry does more than just catch fatal errors, learn more about how to use Sentry from their [JavaScript usage docs](https://docs.sentry.io/platforms/javascript/).
267