From d27ee9d9d44b8e80496e89456192518b1842821c Mon Sep 17 00:00:00 2001 From: Daniel Sutton Date: Fri, 15 May 2026 17:55:50 +0100 Subject: [PATCH] fix(webapp): collapse Prisma P1001 errors into a single Sentry issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DB outages currently produce hundreds of distinct Sentry issues — one per call site — which buries other alerts. Add a beforeSend rule that detects err.code === "P1001" (KnownRequestError when a connection drops mid-query) or err.errorCode === "P1001" (InitializationError when the client fails to connect at startup) and assigns a stable fingerprint plus a db_unreachable tag so all P1001 events collapse into one issue regardless of stack trace. The rule list is extensible — additional fan-out errors can be added with one entry. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../webapp-sentry-fingerprint-p1001.md | 6 ++++ apps/webapp/sentry.server.ts | 33 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 .server-changes/webapp-sentry-fingerprint-p1001.md diff --git a/.server-changes/webapp-sentry-fingerprint-p1001.md b/.server-changes/webapp-sentry-fingerprint-p1001.md new file mode 100644 index 0000000000..dd2f1ecc55 --- /dev/null +++ b/.server-changes/webapp-sentry-fingerprint-p1001.md @@ -0,0 +1,6 @@ +--- +area: webapp +type: improvement +--- + +Group Prisma P1001 ("Can't reach database server") errors into a single Sentry issue via a `beforeSend` fingerprint rule, so DB outages no longer fan out into hundreds of distinct issues that bury other alerts. Adds a small extensible rule table for future collapsing rules. diff --git a/apps/webapp/sentry.server.ts b/apps/webapp/sentry.server.ts index ee84c1d0e3..7f8f6deb62 100644 --- a/apps/webapp/sentry.server.ts +++ b/apps/webapp/sentry.server.ts @@ -1,6 +1,25 @@ import * as Sentry from "@sentry/remix"; import { addOtelTraceContextToEvent } from "./app/utils/sentryTraceContext.server"; +// Rules for collapsing high-volume errors into a single Sentry issue. +// Without this, e.g. a DB outage produces hundreds of distinct issues — +// one per stack trace — which buries other alerts. Add a new rule here +// when you spot another error that fans out across call sites. Keep +// predicates cheap (string compare, not regex over stack traces). +const FINGERPRINT_RULES: Array<{ + match: (err: { code?: unknown; errorCode?: unknown; name?: unknown }) => boolean; + fingerprint: string; + tags?: Record; +}> = [ + { + // Prisma surfaces P1001 on `code` for KnownRequestError (mid-query connection drop) + // and `errorCode` for InitializationError (client failed to connect at startup). + match: (err) => err.code === "P1001" || err.errorCode === "P1001", + fingerprint: "prisma-p1001-db-unreachable", + tags: { db_unreachable: "true" }, + }, +]; + if (process.env.SENTRY_DSN) { console.log("🔭 Initializing Sentry"); @@ -29,6 +48,20 @@ if (process.env.SENTRY_DSN) { // and stay visible. ignoreErrors: ["queryRoute() call aborted", /^ServiceValidationError(?::|$)/], includeLocalVariables: false, + + beforeSend(event, hint) { + const err = hint.originalException as + | { code?: unknown; errorCode?: unknown; name?: unknown } + | undefined; + if (!err) return event; + + const rule = FINGERPRINT_RULES.find((r) => r.match(err)); + if (!rule) return event; + + event.fingerprint = [rule.fingerprint]; + if (rule.tags) event.tags = { ...event.tags, ...rule.tags }; + return event; + }, }); Sentry.addEventProcessor(addOtelTraceContextToEvent);