xref: /expo/docs/pages/guides/using-sentry.mdx (revision 0d0fb8eb)
1---
2title: Use Sentry
3maxHeadingDepth: 4
4description: A guide on installing and configuring Sentry for crash reporting.
5---
6
7import { ConfigReactNative } from '~/components/plugins/ConfigSection';
8import PlatformsSection from '~/components/plugins/PlatformsSection';
9import { Collapsible } from '~/ui/components/Collapsible';
10import { Terminal } from '~/ui/components/Snippet';
11import { Step } from '~/ui/components/Step';
12import { Tab, Tabs } from '~/ui/components/Tabs';
13import { CODE } from '~/ui/components/Text';
14
15[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**.
16
17It 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.
18
19## Why sentry-expo?
20
21- Sentry treats React Native as a first-class citizen and we have collaborated with Sentry to make sure Expo is, too.
22- It's very easy to set up and use
23- It scales to meet the demands of even the largest projects.
24- We trust it for our projects at Expo.
25- It is free for up to 5,000 events per month.
26- It streamlines your error-reporting code across iOS, Android, and web
27
28> Native crash reporting is not available in Expo Go, it is only available in standalone builds or development builds.
29
30<PlatformsSection title="Platform compatibility" android emulator ios simulator web />
31
32## Install and configure Sentry
33
34<Step label="1">
35
36### Sign up for a Sentry account and create a project
37
38Before 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:
39
40<Step label="1.1">
41
42[Sign up for Sentry](https://sentry.io/signup/) (it's free), and create a project in your
43Dashboard. Take note of your **organization slug**, **project name**, and **`DSN`** as you'll need
44them later:
45
46- **organization slug** is available in your **Organization settings** tab
47- **project name** is available in your project's **Settings** > **Projects** tab (find it in the list)
48- **`DSN`** is available in your project's **Settings** > **Projects** > **Project name** > **Client Keys
49  (DSN)** tab.
50
51</Step>
52
53<Step label="1.2">
54
55Go to the [Sentry API section](https://sentry.io/settings/account/api/auth-tokens/), and create an
56**auth token**. The token requires the scopes: `org:read`, `project:releases`, and
57`project:write`. Save them.
58
59</Step>
60
61Once you have each of these: organization slug, project name, DSN, and auth token, you're all set!
62
63</Step>
64
65<Step label="2">
66
67### Installation
68
69In your project directory, run:
70
71<Terminal cmd={['$ npx expo install sentry-expo']} />
72
73`sentry-expo` also requires some additional Expo module packages. To install them, run:
74
75<Terminal
76  cmd={[
77    '$ npx expo install expo-application expo-constants expo-device @sentry/react-native',
78  ]}
79/>
80
81</Step>
82
83<Step label="3">
84
85### Code
86
87#### Initialization
88
89Add the following to your app's main file such as **App.js**:
90
91```js
92import * as Sentry from 'sentry-expo';
93
94Sentry.init({
95  dsn: 'YOUR DSN HERE',
96  enableInExpoDevelopment: true,
97  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
98});
99```
100
101#### Usage
102
103Depending 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:
104
105- For React Native, access any `@sentry/react-native` exports with `Sentry.Native.*`
106- For web, access any `@sentry/browser` exports with `Sentry.Browser.*`
107
108```js
109// Access any @sentry/react-native exports via:
110// Sentry.Native.*
111
112// Access any @sentry/browser exports via:
113// Sentry.Browser.*
114
115// The following example uses `captureException()` from Sentry.Native.* to capture errors:
116try {
117  // your code
118} catch (error) {
119  Sentry.Native.captureException(error);
120}
121```
122
123</Step>
124
125<Step label="4">
126
127### App Configuration
128
129Configuring `sentry-expo` is done through the config plugin in your [app config](/workflow/configuration/).
130
131<ConfigReactNative>
132
133If you use bare workflow, **you should not use the `plugins` property in app config**. Instead, run `yarn sentry-wizard -i reactNative -p ios android` to configure your native projects. This `sentry-wizard` command will add an extra import statement and `Sentry.init` to your project's root file (usually **App.js**) as shown below. Make sure you remove it, however, keep the `sentry-expo` import and original `Sentry.init` call.
134
135```js
136import * as Sentry from '@sentry/react-native';
137
138Sentry.init({
139  dsn: 'YOUR DSN',
140});
141```
142
143</ConfigReactNative>
144
145#### Configure a `postPublish` hook
146
147Add `expo.hooks` property to your project's **app.json** or **app.config.js** file:
148
149```json app.json
150{
151  "expo": {
152    /* @hide ... your existing configuration */ /* @end */
153    "hooks": {
154      "postPublish": [
155        {
156          "file": "sentry-expo/upload-sourcemaps",
157          "config": {
158            "organization": "sentry org slug, or use the `SENTRY_ORG` environment variable",
159            "project": "sentry project name, or use the `SENTRY_PROJECT` environment variable"
160          }
161        }
162      ]
163    }
164  }
165}
166```
167
168To upload the source map to Sentry, you must create a [Sentry auth token](https://docs.sentry.io/product/cli/configuration/). After creating your Sentry auth token [here](https://sentry.io/settings/account/api/), you can configure this token through the `SENTRY_AUTH_TOKEN` environment variable in [EAS Build](/build-reference/variables/#using-secrets-in-environment-variables).
169
170> **warning** Never commit secrets to your repository. Keep the Sentry auth token in a safe place, outside your repository and use the environment variable instead.
171
172Besides the auth token, you can also configure the following options through environment variables:
173
174- organization → `SENTRY_ORG`
175- project → `SENTRY_PROJECT`
176
177<Collapsible summary="Additional configuration options">
178
179In addition to the required config fields above, you can also provide these **optional** fields:
180
181- `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.
182- `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.
183- `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.**
184- `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.**
185- `url`: your Sentry URL, only necessary when self-hosting Sentry.
186
187> You can also use environment variables for your config, if you prefer:
188>
189> - setCommits → `SENTRY_SET_COMMITS`
190> - deployEnv → `SENTRY_DEPLOY_ENV`
191> - distribution → `SENTRY_DIST`
192> - release → `SENTRY_RELEASE`
193> - url → `SENTRY_URL`
194
195</Collapsible>
196
197#### Add the Config Plugin
198
199Add `expo.plugins` to your project's **app.json** or **app.config.js** file:
200
201{/* prettier-ignore */}
202```json app.json
203{
204  "expo": {
205    "plugins": ["sentry-expo"]
206    /* @hide ... your existing configuration */ /* @end */
207  }
208}
209```
210
211</Step>
212
213## Source Maps
214
215{/* TODO: Drop `expo publish` mention */}
216
217With the `postPublish` hook in place, now all you need to do is run `expo publish` and the source maps 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.
218
219> This hook can also be used as a `postExport` hook if you're [self-hosting your updates](../distribution/custom-updates-server.mdx).
220
221### Uploading source maps at build time
222
223With `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 source maps 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:
224
225- Your `release` will automatically be set to Sentry's expected value- `${bundleIdentifier}@${version}+${buildNumber}` (iOS) or `${androidPackage}@${version}+${versionCode}` (Android).
226- Your `dist` will automatically be set to Sentry's expected value: `${buildNumber}` (iOS) or `${versionCode}` (Android).
227- The configuration for build time source maps comes from the **android/sentry.properties** and **ios/sentry.properties** files. For more information, see [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).
228- Configuration for `expo publish` and `npx expo export` for projects is done via **app.json**, whether using bare workflow or not.
229
230Skipping or misconfiguring either of these can lead to invalid source maps, and you won't see human-readable stacktraces in your errors.
231
232### Uploading source maps for updates
233
234> This requires SDK 47, with `[email protected]` or above and `[email protected]` or above.
235
236If you're using EAS Update, or if you're self-hosting your updates (this means you run `npx expo export` manually), you need to take the following steps to upload the source maps for your update to Sentry:
237
238- Run `eas update`. This will generate a **dist** folder in your project root, which contains your JavaScript bundles and source maps. This command will also output the 'Android update ID' and 'iOS update ID' that we'll need in the next step.
239- Copy or rename the bundle names in the **dist/bundles** folder to match **index.android.bundle** (Android) or **main.jsbundle** (iOS).
240- Next, you can use the Sentry CLI to upload your bundles and source maps:
241  - `release name` should be set to `${bundleIdentifier}@${version}+${buildNumber}` (iOS) or `${androidPackage}@${version}+${versionCode}` (Android), so for example `[email protected]+1`.
242  - `dist` should be set to the Update ID that `eas update` generated.
243
244<Tabs>
245  <Tab label="Android">
246    <Terminal
247      cmd={[
248        '$ node_modules/@sentry/cli/bin/sentry-cli releases \\',
249        '    files <release name> \\',
250        '    upload-sourcemaps \\',
251        '    --dist <Android Update ID> \\',
252        '    --rewrite \\',
253        '    dist/bundles/index.android.bundle dist/bundles/android-<hash>.map',
254      ]}
255    />
256  </Tab>
257  <Tab label="iOS">
258    <Terminal
259      cmd={[
260        '$ node_modules/@sentry/cli/bin/sentry-cli releases \\',
261        '    files <release name> \\',
262        '    upload-sourcemaps \\',
263        '    --dist <iOS Update ID> \\',
264        '    --rewrite \\',
265        '    dist/bundles/main.jsbundle dist/bundles/ios-<hash>.map',
266      ]}
267    />
268  </Tab>
269</Tabs>
270
271For more information, see Sentry's [instructions for uploading the bundle and source maps](https://docs.sentry.io/platforms/react-native/sourcemaps/#3-upload-the-bundle-and-source-maps).
272
273The steps above define a new 'dist' on Sentry, under the same release as your full app build, and associate the source maps with this new dist. If you want to customize this behavior, you can pass in your own values for `release` and `dist` when you initialize Sentry in your code. For example:
274
275```js
276import * as Sentry from 'sentry-expo';
277import * as Updates from 'expo-updates';
278
279Sentry.init({
280  dsn: 'YOUR DSN',
281  release: 'my release name',
282  dist: 'my dist',
283});
284```
285
286These values should match the values you pass to the `sentry-cli` when uploading your source maps.
287
288### Testing Sentry
289
290When 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.
291
292[`sentry-testkit`](https://zivl.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.
293
294For more information on how to get started, see [`sentry-testkit` documentation](https://zivl.github.io/sentry-testkit/).
295
296> If you're using `jest`, make sure to add `@sentry/.*` and `sentry-expo` to your `transformIgnorePatterns`.
297
298## Error reporting semantics
299
300In 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.
301
302## Disabled by default in dev
303
304Unless `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.
305
306## Troubleshooting
307
308<Collapsible summary={<>I'm seeing <CODE>error: project not found</CODE> in my build logs</>}>
309
310This error is caused by the script that tries to upload source maps during build.
311
312Make sure your `organization`, `project` and `authToken` properties are set correctly.
313
314</Collapsible>
315
316<Collapsible summary={<><CODE>expo-dev-client</CODE> transactions never finish</>}>
317
318This error is caused by the HTTP request tracking, which creates spans for log requests to the development server. To fix this, stop creating spans by adding the following code snippet:
319
320```js
321import * as Sentry from 'sentry-expo';
322import * as Network from 'expo-network';
323
324const devServerPort = 8081;
325let devServerIpAddress: string | null = null;
326Network.getIpAddressAsync().then(ip => {
327  devServerIpAddress = ip;
328});
329
330Sentry.init({
331  tracesSampleRate: 1.0,
332  integrations: [
333    new Sentry.Native.ReactNativeTracing({
334      shouldCreateSpanForRequest: url => {
335        return !__DEV__ || !url.startsWith(`http://${devServerIpAddress}:${devServerPort}/logs`);
336      },
337    }),
338  ],
339});
340```
341
342</Collapsible>
343
344## Learn more about Sentry
345
346Sentry does more than just catch fatal errors, learn more about how to use Sentry from their [JavaScript usage](https://docs.sentry.io/platforms/javascript/) documentation.
347