Chore(sentry): skip Sentry init in dev runs

A local pnpm dev with a DSN in .env reported every half-finished edit
against the production projects. The frontend gate now also checks
import.meta.env.DEV; the backend bootstrap skips init under
SENTRY_ENVIRONMENT=development, mirroring the cron check-in rule.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
jason5ng32andClaude Fable 5.1 committed 2026-09-03 10:55:10 +08:00
1 parent a8f75bdb46
commit 244a121e98
4 files changed
+22 -12

No files matched your search

+3 -1
View File
@@ -60,7 +60,9 @@ currently `dns-resolvers.js`, the country-annotated resolver list behind
Root-level `sentry-instrument.js` (loaded via `node --import` *before*
express, so ESM loader hooks can auto-instrument route tracing) does the
init; `backend-server.js` attaches `setupExpressErrorHandler` after the
routes. No `SENTRY_DSN_BACKEND` → `@sentry/node` never loads. Handlers
routes. No `SENTRY_DSN_BACKEND` → `@sentry/node` never loads;
`SENTRY_ENVIRONMENT=development` skips the init, so a local run reports
nothing (same rule the cron check-ins already follow). Handlers
never import Sentry or capture manually: uncaught throws and 5xx traces
are automatic; caught failures stay on the logger — a hook in
`common/logger.js` mirrors warn+ to Sentry Logs and elevates error+ to
+3 -1
View File
@@ -76,7 +76,9 @@ replaces the map, and Home clears it on unmount — shortcuts are home-route onl
### Error monitoring (Sentry) is env-gated and invisible to app code
No `VITE_SENTRY_DSN_FRONTEND` → no Sentry code in the bundle at all
(build-time-gated dynamic import, like `firebase-init.js`). Rules:
(build-time-gated dynamic import, like `firebase-init.js`). The same gate in
`main.js` skips the load under `import.meta.env.DEV`, so a `pnpm dev` run
reports nothing even with a DSN in `.env`. Rules:
- **Never import `@sentry/vue` in app code** — a static import drags the SDK
into the main bundle. All config lives in `sentry-init.js`.
+10 -8
View File
@@ -66,16 +66,18 @@ const store = useMainStore(pinia);
app.use(i18n);
app.use(router);
// Sentry — build-time env gate: without the DSN the chunk neither ships nor
// loads. The SDK chunk stays OFF the boot critical path: it loads after
// mount (see the mount chain's finally below) so it never competes with the
// locale pack the first render waits on. Until init, a tiny buffer catches
// uncaught errors / rejections — and any of them triggers an immediate
// load, so a boot that never reaches mount still reports. Perf data
// survives the late init (buffered observers, backdated pageload span).
// Sentry — build-time env gate: without the DSN, or in a dev server run, the
// chunk neither ships nor loads (local runs would otherwise report every
// experiment against the production project). The SDK chunk stays OFF the
// boot critical path: it loads after mount (see the mount chain's finally
// below) so it never competes with the locale pack the first render waits
// on. Until init, a tiny buffer catches uncaught errors / rejections — and
// any of them triggers an immediate load, so a boot that never reaches mount
// still reports. Perf data survives the late init (buffered observers,
// backdated pageload span).
const earlyErrors = [];
let loadSentry = () => {};
if (import.meta.env.VITE_SENTRY_DSN_FRONTEND) {
if (import.meta.env.VITE_SENTRY_DSN_FRONTEND && !import.meta.env.DEV) {
const onEarlyError = (event) => {
earlyErrors.push(event);
loadSentry();
+6 -2
View File
@@ -5,14 +5,18 @@
//
// Gated on SENTRY_DSN_BACKEND, same philosophy as the frontend: when the env
// var is unset this module does nothing and @sentry/node is never even
// loaded. backend-server.js attaches the matching Express error handler.
// loaded. SENTRY_ENVIRONMENT=development skips init too, so a local run never
// reports. backend-server.js attaches the matching Express error handler.
import dotenv from 'dotenv';
import { scrubBreadcrumb, scrubEventRequest, scrubSpan } from './common/sentry-scrub.js';
dotenv.config({ quiet: true });
if (process.env.SENTRY_DSN_BACKEND) {
// SENTRY_ENVIRONMENT=development (a local `pnpm dev` machine) skips init:
// experiments in progress are not production signal, same rule as the cron
// check-ins in common/sentry-cron.js.
if (process.env.SENTRY_DSN_BACKEND && process.env.SENTRY_ENVIRONMENT !== 'development') {
const Sentry = await import('@sentry/node');
Sentry.init({
dsn: process.env.SENTRY_DSN_BACKEND,