A guide on installing and configuring Sentry for crash reporting.
Sentry is a crash reporting platform that provides you with real-time insight into production deployments with info to reproduce and fix crashes.
It 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.
Native crash reporting is not available in Expo Go, it is only available in standalone builds or development builds.
Android Device | Android Emulator | iOS Device | iOS Simulator | Web |
---|---|---|---|---|
1
Before 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:
1.1
Sign up for Sentry (it's free), and create a project in your
Dashboard. Take note of your organization slug, project name, and DSN
as you'll need
them later:
DSN
is available in your project's Settings > Projects > Project name > Client Keys
(DSN) tab.1.2
Go to the Sentry API section, and create an
auth token. The token requires the scopes: org:read
, project:releases
, and
project:write
. Save them.
Once you have each of these: organization slug, project name, DSN, and auth token, you're all set!
2
In your project directory, run:
-
npx expo install sentry-expo
sentry-expo
also requires some additional Expo module packages. To install them, run:
-
npx expo install expo-application expo-constants expo-device @sentry/react-native
3
Add the following to your app's main file such as App.js:
import * as Sentry from 'sentry-expo';
Sentry.init({
dsn: 'YOUR DSN HERE',
enableInExpoDevelopment: true,
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
});
Depending 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:
@sentry/react-native
exports with Sentry.Native.*
@sentry/browser
exports with Sentry.Browser.*
// Access any @sentry/react-native exports via:
// Sentry.Native.*
// Access any @sentry/browser exports via:
// Sentry.Browser.*
// The following example uses `captureException()` from Sentry.Native.* to capture errors:
try {
// your code
} catch (error) {
Sentry.Native.captureException(error);
}
4
Configuring sentry-expo
is done through the config plugin in your app config.
If 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.
import * as Sentry from '@sentry/react-native';
Sentry.init({
dsn: 'YOUR DSN',
});
postPublish
hookAdd expo.hooks
property to your project's app.json or app.config.js file:
{
"expo": {
%%placeholder-start%%... your existing configuration %%placeholder-end%%
"hooks": {
"postPublish": [
{
"file": "sentry-expo/upload-sourcemaps",
"config": {
"organization": "sentry org slug, or use the `SENTRY_ORG` environment variable",
"project": "sentry project name, or use the `SENTRY_PROJECT` environment variable"
}
}
]
}
}
}
To upload the source map to Sentry, you must create a Sentry auth token. After creating your Sentry auth token here, you can configure this token through the SENTRY_AUTH_TOKEN
environment variable in EAS Build.
Never commit secrets to your repository. Keep the Sentry auth token in a safe place, outside your repository and use the environment variable instead.
Besides the auth token, you can also configure the following options through environment variables:
SENTRY_ORG
SENTRY_PROJECT
In addition to the required config fields above, you can also provide these optional fields:
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.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.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.release
: The name you'd like to give your release (for example, 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.url
: your Sentry URL, only necessary when self-hosting Sentry.You can also use environment variables for your config, if you prefer:
- setCommits →
SENTRY_SET_COMMITS
- deployEnv →
SENTRY_DEPLOY_ENV
- distribution →
SENTRY_DIST
- release →
SENTRY_RELEASE
- url →
SENTRY_URL
Add expo.plugins
to your project's app.json or app.config.js file:
{
"expo": {
"plugins": ["sentry-expo"]
%%placeholder-start%%... your existing configuration %%placeholder-end%%
}
}
With 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.
This hook can also be used as a
postExport
hook if you're self-hosting your updates.
With expo-updates
, release builds of both Android and iOS 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:
release
will automatically be set to Sentry's expected value- ${bundleIdentifier}@${version}+${buildNumber}
(iOS) or ${androidPackage}@${version}+${versionCode}
(Android).dist
will automatically be set to Sentry's expected value: ${buildNumber}
(iOS) or ${versionCode}
(Android).expo publish
and npx expo export
for projects is done via app.json, whether using bare workflow or not.Skipping or misconfiguring either of these can lead to invalid source maps, and you won't see human-readable stacktraces in your errors.
This requires SDK 47, with
sentry-expo@6.0.0
or above andexpo-updates@0.15.5
or above.
If 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:
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.release name
should be set to ${bundleIdentifier}@${version}+${buildNumber}
(iOS) or ${androidPackage}@${version}+${versionCode}
(Android), so for example com.domain.myapp@1.0.0+1
.dist
should be set to the Update ID that eas update
generated.-
node_modules/@sentry/cli/bin/sentry-cli releases \
files <release name> \
upload-sourcemaps \
--dist <Android Update ID> \
--rewrite \
dist/bundles/index.android.bundle dist/bundles/android-<hash>.map
-
node_modules/@sentry/cli/bin/sentry-cli releases \
files <release name> \
upload-sourcemaps \
--dist <iOS Update ID> \
--rewrite \
dist/bundles/main.jsbundle dist/bundles/ios-<hash>.map
For more information, see Sentry's instructions for uploading the bundle and source maps.
The 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:
import * as Sentry from 'sentry-expo';
import * as Updates from 'expo-updates';
Sentry.init({
dsn: 'YOUR DSN',
release: 'my release name',
dist: 'my dist',
});
These values should match the values you pass to the sentry-cli
when uploading your source maps.
When 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.
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.
For more information on how to get started, see sentry-testkit
documentation.
If you're using
jest
, make sure to add@sentry/.*
andsentry-expo
to yourtransformIgnorePatterns
.
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.
Unless 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.
error: project not found
in my build logsThis error is caused by the script that tries to upload source maps during build.
Make sure your organization
, project
and authToken
properties are set correctly.
expo-dev-client
transactions never finishThis error is caused by the HTTP request tracking, which creates spans for log requests (Starting 'http.client' span on transaction...
) to the development server. To fix this, stop creating spans by adding the following code snippet:
import * as Sentry from 'sentry-expo';
import Constants from 'expo-constants';
Sentry.init({
tracesSampleRate: 1.0,
integrations: [
new Sentry.Native.ReactNativeTracing({
shouldCreateSpanForRequest: url => {
return !__DEV__ || !url.startsWith(`http://${Constants.expoConfig.hostUri}/logs`);
},
}),
],
});
Sentry does more than just catch fatal errors, learn more about how to use Sentry from their JavaScript usage documentation.