Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .server-changes/webapp-sentry-fingerprint-p1001.md
Original file line number Diff line number Diff line change
@@ -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.
33 changes: 33 additions & 0 deletions apps/webapp/sentry.server.ts
Original file line number Diff line number Diff line change
@@ -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<string, string>;
}> = [
{
// 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" },
},
];
Comment thread
d-cs marked this conversation as resolved.

if (process.env.SENTRY_DSN) {
console.log("🔭 Initializing Sentry");

Expand Down Expand Up @@ -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);
Expand Down