2026-09-03 13:59:13 -03:00
|
|
|
# 0002. Browser error and transaction telemetry with Sentry
|
|
|
|
|
|
|
|
|
|
## Status
|
|
|
|
|
|
|
|
|
|
Accepted
|
|
|
|
|
|
|
|
|
|
## Context
|
|
|
|
|
|
|
|
|
|
The SeaHaven admin SPA has no centralized browser error reporting or distributed
|
|
|
|
|
transaction tracing. Operational failures therefore have to be reconstructed
|
|
|
|
|
from user reports and isolated backend logs. We need browser navigation and API
|
|
|
|
|
request transactions to join the backend trace while preserving the existing UI,
|
2026-09-03 17:12:49 -03:00
|
|
|
routing, authentication, and server-state behavior. Every emitted transaction
|
|
|
|
|
must also identify its exact build, trace, transaction, operation, function, and
|
|
|
|
|
opaque actor without sending credentials, request bodies, query values, or
|
|
|
|
|
personal data.
|
2026-09-03 13:59:13 -03:00
|
|
|
|
|
|
|
|
## Decision
|
|
|
|
|
|
|
|
|
|
Use the pinned `@sentry/react` 10.73.0 SDK. Initialize it before the application
|
|
|
|
|
router is created, and wrap `createBrowserRouter` with Sentry's current React
|
|
|
|
|
Router compatibility API. Configure the browser tracing integration with a 100%
|
|
|
|
|
transaction sample rate, and propagate trace headers only to the SPA origin and
|
2026-09-03 15:53:50 -03:00
|
|
|
the configured `VITE_API_URL` base. Pass `Sentry.reactErrorHandler()` as the
|
|
|
|
|
`onCaughtError`, `onUncaughtError`, and `onRecoverableError` callbacks of
|
|
|
|
|
`ReactDOM.createRoot`, so React 19's root error hooks capture caught, uncaught,
|
|
|
|
|
and recoverable component errors as Sentry events.
|
2026-09-03 13:59:13 -03:00
|
|
|
|
2026-09-03 17:12:49 -03:00
|
|
|
All shared API helpers, direct Ky calls, vendor-link `fetch` calls, and vendor
|
|
|
|
|
document `XMLHttpRequest` calls run inside explicit `http.client` transactions.
|
|
|
|
|
They use normalized route templates and attach `code.function`, `operation.type`,
|
|
|
|
|
HTTP method, `trace_id`, and `transaction_id`. Browser navigation transactions
|
|
|
|
|
receive the same searchable trace identifiers in `beforeSendTransaction`.
|
|
|
|
|
Authenticated sessions set only the application's opaque numeric/string user ID;
|
|
|
|
|
logout and session expiry clear it.
|
|
|
|
|
|
2026-09-03 13:59:13 -03:00
|
|
|
The DSN comes from `VITE_SENTRY_DSN`. It is intentionally treated as public
|
|
|
|
|
browser configuration because every `VITE_` value is embedded in the built
|
2026-09-03 15:10:01 -03:00
|
|
|
JavaScript. `.env.production` commits the public DSN of the real
|
|
|
|
|
`shoc-frontend` Sentry project, so dev and staging deploys are live; a missing
|
|
|
|
|
or blank DSN in any other build leaves telemetry inactive without preventing
|
2026-09-03 13:59:13 -03:00
|
|
|
the application from starting. Default personally identifiable information
|
|
|
|
|
collection remains disabled.
|
|
|
|
|
|
2026-09-03 15:10:01 -03:00
|
|
|
The Sentry environment label comes from `VITE_SENTRY_ENVIRONMENT` when set and
|
|
|
|
|
non-blank, falling back to the Vite build mode otherwise. The committed
|
|
|
|
|
`.env.production` labels dev deploys `development`, the staging deploy job
|
|
|
|
|
overrides the label to `staging`, and a future production pipeline can set
|
|
|
|
|
`production` without code changes.
|
|
|
|
|
|
2026-09-03 17:12:49 -03:00
|
|
|
Every deployment embeds `shoc-frontend@<40-character commit SHA>` as the Sentry
|
|
|
|
|
release and exposes the same SHA as the `app.commit` tag. CI fails if it cannot
|
|
|
|
|
resolve that identity. Vite creates hidden source maps, and the dev/staging
|
|
|
|
|
deployment workflows upload them to the private `shoc-frontend` Sentry project
|
|
|
|
|
using the repository's `SENTRY_AUTH_TOKEN` secret. The public S3 sync explicitly
|
|
|
|
|
excludes `*.map`; the upload credential is never available to the browser build.
|
|
|
|
|
|
|
|
|
|
Before-send processors reduce request data to normalized URL plus HTTP method,
|
|
|
|
|
reduce users to opaque ID only, attach native trace/transaction identifiers as
|
|
|
|
|
searchable tags, and reduce breadcrumbs to safe network method/status/normalized
|
|
|
|
|
URL metadata. Root and child span attributes use the same allowlist, retaining
|
|
|
|
|
function, operation, actor type, normalized route, method/status, service host,
|
|
|
|
|
timing, and native IDs while removing raw URLs and query values. Bodies, headers,
|
|
|
|
|
cookies, query strings/values, free-form breadcrumb messages, usernames, email
|
|
|
|
|
addresses, IP addresses, tokens, and filenames are not intentionally sent.
|
|
|
|
|
`sendDefaultPii` remains disabled.
|
2026-09-03 13:59:13 -03:00
|
|
|
|
|
|
|
|
### Alternatives considered
|
|
|
|
|
|
|
|
|
|
- **Manual error and timing calls** — rejected because they would miss route
|
|
|
|
|
transitions and distributed request context, and would require every feature
|
|
|
|
|
to maintain its own instrumentation.
|
|
|
|
|
- **Propagate tracing headers to every request** — rejected because third-party
|
|
|
|
|
requests must not receive SeaHaven trace metadata and broad propagation can
|
|
|
|
|
introduce cross-origin request failures.
|
2026-09-03 17:12:49 -03:00
|
|
|
- **Publish source maps with the SPA** — rejected because source code belongs in
|
|
|
|
|
Sentry's private artifact store, not the public application bucket.
|
2026-09-03 13:59:13 -03:00
|
|
|
|
|
|
|
|
## Consequences
|
|
|
|
|
|
|
|
|
|
- Browser navigations and API requests are recorded as connected transactions
|
|
|
|
|
when the deployment supplies a valid DSN.
|
2026-09-03 15:10:01 -03:00
|
|
|
- Events are labeled by `VITE_SENTRY_ENVIRONMENT` (`development` on dev
|
|
|
|
|
deploys, `staging` on the staging job), falling back to the Vite build mode
|
|
|
|
|
when unset.
|
2026-09-03 13:59:13 -03:00
|
|
|
- Every transaction is sampled. This meets the current requirement but increases
|
|
|
|
|
event volume and should be reviewed against Sentry quota and retention after
|
|
|
|
|
real traffic is measured.
|
|
|
|
|
- Cross-origin API tracing depends on the backend accepting `sentry-trace` and
|
|
|
|
|
`baggage` request headers; the current API CORS policy allows request headers.
|
2026-09-03 17:12:49 -03:00
|
|
|
- Deployed stack traces resolve against the exact commit's private source maps
|
|
|
|
|
once the scoped upload secret is present and the deployment workflow runs.
|
2026-09-03 13:59:13 -03:00
|
|
|
- Rollback is isolated: remove `@sentry/react`, the initialization module and
|
|
|
|
|
import, restore the unwrapped router factory, and remove the Sentry env entries.
|