The Sentry DSNs were hardcoded in journal/server.ts, planner/server.ts, and journal/app/lib/sentry.client.ts. Self-hosted instances inheriting the trails.cool flagship DSN would silently ship their errors to our Sentry account. Now each init site reads its DSN from env: - journal/server.ts: SENTRY_DSN (server runtime env) - planner/server.ts: SENTRY_DSN (server runtime env) - journal/app/lib/sentry.client.ts: VITE_SENTRY_DSN (build-time bake) The flagship DSN is kept as the fallback so the production deploy keeps reporting without an infra change — but self-hosters can: - set SENTRY_DSN=\"\" / VITE_SENTRY_DSN=\"\" to ship their own builds without Sentry, or - set SENTRY_DISABLED=true to skip init entirely at runtime, or - set SENTRY_DSN=/VITE_SENTRY_DSN= to their own DSN. Follow-up: a future PR can remove the hardcoded fallbacks once infrastructure/docker-compose.yml + the cd-apps.yml workflow are wired to pass SENTRY_DSN explicitly. That requires SOPS edits + workflow changes I want isolated from this purely-code change. Full repo: pnpm typecheck, pnpm lint, pnpm test all green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
49 lines
1.6 KiB
TypeScript
49 lines
1.6 KiB
TypeScript
import * as Sentry from "@sentry/react";
|
|
import { useEffect } from "react";
|
|
import { useLocation, useNavigationType, createRoutesFromChildren, matchRoutes } from "react-router";
|
|
import { browserSentryConfig } from "@trails-cool/sentry-config";
|
|
|
|
let initialized = false;
|
|
|
|
// Build-time DSN injection: `VITE_SENTRY_DSN` (if set during `pnpm build`)
|
|
// overrides the flagship default so self-hosters can ship their own
|
|
// Sentry project. Set it to `""` (empty string) to disable Sentry on
|
|
// the client entirely.
|
|
const FLAGSHIP_JOURNAL_DSN =
|
|
"https://a32ffcc575d34be072e91b20f247eeee@o4509530546634752.ingest.de.sentry.io/4509530555547728";
|
|
const CLIENT_DSN =
|
|
(import.meta.env as Record<string, string | undefined>).VITE_SENTRY_DSN ??
|
|
FLAGSHIP_JOURNAL_DSN;
|
|
|
|
export function initSentryClient() {
|
|
if (initialized) return;
|
|
initialized = true;
|
|
if (!CLIENT_DSN) return;
|
|
|
|
Sentry.init({
|
|
dsn: CLIENT_DSN,
|
|
integrations: [
|
|
Sentry.reactRouterV7BrowserTracingIntegration({
|
|
useEffect,
|
|
useLocation,
|
|
useNavigationType,
|
|
createRoutesFromChildren,
|
|
matchRoutes,
|
|
}),
|
|
],
|
|
...browserSentryConfig("journal client", import.meta.env),
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Tear down the Sentry client on logout. After this call, `Sentry.captureException`
|
|
* and other hub methods become no-ops until `initSentryClient` is called again.
|
|
*
|
|
* Fire-and-forget: the close flush happens async, but we don't want to block the
|
|
* logout UI on it.
|
|
*/
|
|
export function stopSentryClient() {
|
|
if (!initialized) return;
|
|
initialized = false;
|
|
void Sentry.close();
|
|
}
|