Skip to main content

Sentry

What it is​

Sentry collects errors from the API, the websites and the mobile app, groups them into issues, and tells you which release (build) each first appeared in. Apps send errors to a DSN, an address specific to one Sentry project.

How to triage issues once it is running is in Sentry (DevOps). This page is the setup.

Why we do it​

Without it, the first sign of a bug is a user complaint, and you cannot tell which build caused it. With release names that match the Docker image tag, an issue leads straight to a commit.

Before you start​

  • A Sentry organisation for the project, created with the team mailbox, owner per OWNERSHIP.md.
  • The list of apps: for example acme-api, acme-web, acme-admin, acme-mobile.
  • The team chat channel for alerts (Slack or Microsoft Teams).

How it fits together​

One project per app, all environments inside it. Each event carries an environment (development, staging, production), and you filter by it.

Steps​

1. Organisation settings​

In Sentry, Settings, Organization:

SettingWhereValue
Require 2FASecurity & PrivacyOn
Data scrubberSecurity & PrivacyOn, with default scrubbers
Prevent storing IP addressesSecurity & PrivacyOn
MembersMembersInvite through the team mailbox domain; roles Member, Admin for leads

2. Create one project per app​

Projects, Create Project, choose the platform (Node.js, Next.js, Flutter), name it after the repo (acme-api). Copy the DSN from Project Settings, Client Keys (DSN).

3. Put the DSN where the app reads it​

AppWhere the DSN goes
APISSM /acme/<env>/api/SENTRY_DSN, injected by the task definition
WebBuild-time environment variable, for example NEXT_PUBLIC_SENTRY_DSN. A DSN is not secret; it only allows sending events
MobileA build-time define per flavor, for example --dart-define=SENTRY_DSN=...

4. Initialise the SDK​

API (Node). Load this first, before any other import:

// src/instrument.ts
import * as Sentry from '@sentry/node';

if (process.env.SENTRY_DSN && process.env.NODE_ENV !== 'development-local') {
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.SENTRY_ENVIRONMENT, // development | staging | production
release: process.env.SENTRY_RELEASE, // acme-api@<image tag>
sendDefaultPii: false,
tracesSampleRate: 0.1,
});
}

Web (Next.js): run npx @sentry/wizard@latest -i nextjs and then set the same three values. Mobile (Flutter): sentry_flutter, initialised in main_<flavor>.dart with the flavor's environment.

Laptops send nothing: the init is skipped locally, so a stray DSN cannot fill the quota.

5. Releases and readable stack traces from CI​

  1. Settings, Developer Settings, Organization Tokens, create a token for CI. Store it as a CI secret (SENTRY_AUTH_TOKEN), never in the repo.
  2. In the build, set the release to the image tag and upload maps or symbols:
AppIn CI
APIRelease acme-api@<first 7 chars of commit>, written into the task definition
WebSource maps uploaded by the Sentry build plugin; not served publicly
Mobiledart run sentry_dart_plugin after the release build uploads debug symbols

6. Alerts​

Alerts, Create Alert, Issues:

AlertConditionGoes to
New issue in productionA new issue is created, environment productionTeam channel
Issue spikeNumber of events above a threshold in 1 hour, productionTeam channel and on-call
RegressionA resolved issue happens againTeam channel

Install the Slack or Microsoft Teams integration from Settings, Integrations first, so alerts can post there. Keep spike protection on (it is by default).

Check it worked​

From dev, trigger a test error:

curl -X POST https://api.dev.example.com/debug/sentry-test # a route that throws, dev only

Within a minute an issue appears in acme-api, environment development, with the release name and a readable stack trace pointing at your source file.

If it goes wrong​

You seeIt means
No events at allDSN not set in that environment, or init skipped by the local check
Every deploy shows the same releaseThe release is a fixed value instead of the image tag
Stack traces point at minified codeSource maps or symbols were not uploaded for that release
Quota used up in a dayAn error loop, or rejected requests (4xx) reported as events. Filter them in beforeSend

Rules​

Rule

Do not report every 4xx as an event. One scanner sending bad requests once created about 600 events. Report 5xx and unexpected errors; count 4xx as metrics.

Rule

sendDefaultPii stays false. Never attach request bodies, tokens or personal data to events.

Done when​

  • Organisation with 2FA, data scrubbing, no IP storage.
  • One project per app; DSNs stored per environment.
  • Releases match image tags; source maps and symbols uploaded by CI.
  • Alerts post to the team channel.
  • A test error from dev arrived with a readable stack trace.