Error reporting (Sentry-compatible)
Cinatra ships a Sentry-compatible error-reporting layer. It works against both Sentry (self-hosted or SaaS) and GlitchTip (Sentry-API compatible, lighter to self-host). The application code does not pick — it points at whichever DSN the operator provides.
What gets captured
Section titled “What gets captured”- Unhandled exceptions in route handlers, server components, and server actions, via Next.js
onRequestError - React render errors caught by
src/components/render-error-boundary.tsx - Root-level App Router errors caught by
src/app/global-error.tsx - BullMQ worker failures, with
jobName,jobId, andqueueNametags
Everything is best-effort and isolated: a Sentry-internal failure never crashes a worker, a route handler, or a render.
Disabling Sentry
Section titled “Disabling Sentry”SENTRY_DSN unset → every helper is a no-op. There is no separate “off” flag. This is the dev default.
Coexistence with OpenTelemetry
Section titled “Coexistence with OpenTelemetry”Cinatra already owns its NodeTracerProvider in src/lib/otel-bootstrap.ts and writes spans to Postgres via PostgresSpanExporter. The Sentry SDK is initialised with skipOpenTelemetrySetup: true, and the bootstrap then attaches Sentry’s SentrySpanProcessor, SentrySampler, SentryPropagator, and SentryContextManager to the existing provider. There is exactly one provider.register() call in the codebase.
PII scrubbing
Section titled “PII scrubbing”src/lib/sentry-shared.ts beforeSendFilter redacts:
- Request headers:
authorization,cookie,set-cookie,x-api-key,x-auth-token - Body fields anywhere in nested objects:
password,newPassword,currentPassword,apiKey,secret,token,accessToken,refreshToken,sessionToken,clientSecret,privateKey - Cookies entirely
- User extras outside
id,email,username,ip_address - JSON-stringified bodies that start with
{or[(parsed, redacted, restringified)
Breadcrumb data is filtered with the same rules.
Known scrub gaps (deliberate)
Section titled “Known scrub gaps (deliberate)”- Plain-text bodies (not JSON-shaped) pass through unmodified. Callers MUST NOT log secrets into plain-text request bodies anywhere.
URLSearchParamsandFormDatapayloads pass through unmodified if they reach the Sentry event. Cinatra’s API surface is JSON-heavy so this is a low-impact gap; the Sentry SDK serialises these forms before our hook runs, and the scrubbing of object body keys still applies post-serialisation when the serialised shape is JSON.- The scrubber walks at most 8 levels deep. Beyond that the value is returned verbatim. No real Cinatra payload is that deep, but worth knowing for hand-crafted captures.
Operator runbook
Section titled “Operator runbook”Pointing Cinatra at a backend is a small operator change:
# Server / edge / BullMQ worker captureSENTRY_DSN=https://...@sentry.example.com/123SENTRY_ENVIRONMENT=productionSENTRY_TRACES_SAMPLE_RATE=0.1
# Browser-side capture (Next.js only inlines NEXT_PUBLIC_* envs into the# client bundle). Set this to enable Sentry in the browser. Leave unset to# keep browser-side capture disabled — server / worker capture still works.NEXT_PUBLIC_SENTRY_DSN=https://...@sentry.example.com/123For self-hosted setups, the recommendation is GlitchTip first unless you need full Sentry tracing/replay/release features. GlitchTip stands up on Postgres + Redis only, mirrors the Sentry SDK protocol, and is the lighter operational pick.
Source-map upload is build-time only. Set SENTRY_AUTH_TOKEN, SENTRY_ORG, and SENTRY_PROJECT in CI. Do not set them in production runtime envs.
src/lib/__tests__/sentry.test.ts covers:
shouldInitSentry()returns true only whenSENTRY_DSNis setbeforeSendFilterredacts headers, body fields, cookies, user extraswithSentryServerActionre-throws after capture
File map
Section titled “File map”sentry.client.config.ts/sentry.server.config.ts/sentry.edge.config.ts— runtime init, side-effect imports ofsrc/lib/sentry.tsinstrumentation-client.ts— loads client config at the start of every navigationsrc/instrumentation.ts— exportsonRequestError(runtime-gated dynamic import)src/instrumentation.node.ts— side-effect imports the server config before OTelsrc/lib/sentry.ts—shouldInitSentry,buildSentryClientOptions,beforeSendFilter,captureBackgroundJobError,withSentryServerActionsrc/lib/otel-bootstrap.ts— attaches Sentry OTel pieces to Cinatra’s existing providersrc/lib/background-jobs.ts—worker.on('failed')callscaptureBackgroundJobErrorsrc/app/global-error.tsx,src/components/render-error-boundary.tsx—Sentry.captureExceptionnext.config.ts—withSentryConfigwrapper, gated on build-time envs