Skip to content

Commit d27ee9d

Browse files
d-csclaude
andcommitted
fix(webapp): collapse Prisma P1001 errors into a single Sentry issue
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) <noreply@anthropic.com>
1 parent 5788573 commit d27ee9d

2 files changed

Lines changed: 39 additions & 0 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: improvement
4+
---
5+
6+
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.

apps/webapp/sentry.server.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,25 @@
11
import * as Sentry from "@sentry/remix";
22
import { addOtelTraceContextToEvent } from "./app/utils/sentryTraceContext.server";
33

4+
// Rules for collapsing high-volume errors into a single Sentry issue.
5+
// Without this, e.g. a DB outage produces hundreds of distinct issues —
6+
// one per stack trace — which buries other alerts. Add a new rule here
7+
// when you spot another error that fans out across call sites. Keep
8+
// predicates cheap (string compare, not regex over stack traces).
9+
const FINGERPRINT_RULES: Array<{
10+
match: (err: { code?: unknown; errorCode?: unknown; name?: unknown }) => boolean;
11+
fingerprint: string;
12+
tags?: Record<string, string>;
13+
}> = [
14+
{
15+
// Prisma surfaces P1001 on `code` for KnownRequestError (mid-query connection drop)
16+
// and `errorCode` for InitializationError (client failed to connect at startup).
17+
match: (err) => err.code === "P1001" || err.errorCode === "P1001",
18+
fingerprint: "prisma-p1001-db-unreachable",
19+
tags: { db_unreachable: "true" },
20+
},
21+
];
22+
423
if (process.env.SENTRY_DSN) {
524
console.log("🔭 Initializing Sentry");
625

@@ -29,6 +48,20 @@ if (process.env.SENTRY_DSN) {
2948
// and stay visible.
3049
ignoreErrors: ["queryRoute() call aborted", /^ServiceValidationError(?::|$)/],
3150
includeLocalVariables: false,
51+
52+
beforeSend(event, hint) {
53+
const err = hint.originalException as
54+
| { code?: unknown; errorCode?: unknown; name?: unknown }
55+
| undefined;
56+
if (!err) return event;
57+
58+
const rule = FINGERPRINT_RULES.find((r) => r.match(err));
59+
if (!rule) return event;
60+
61+
event.fingerprint = [rule.fingerprint];
62+
if (rule.tags) event.tags = { ...event.tags, ...rule.tags };
63+
return event;
64+
},
3265
});
3366

3467
Sentry.addEventProcessor(addOtelTraceContextToEvent);

0 commit comments

Comments
 (0)