chore: remove Sentry integration
This commit is contained in:
1 parent
c7fb37356e
commit
1f4aadb3d7
21 files changed
+53
-1960
No files matched your search
@@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import * as Sentry from "@sentry/nextjs";
|
||||
import { Home, RefreshCw } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useTranslations } from "next-intl";
|
||||
@@ -22,7 +21,6 @@ export default function SiteErrorPage({
|
||||
|
||||
useEffect(() => {
|
||||
console.error(error);
|
||||
Sentry.captureException(error);
|
||||
}, [error]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import * as Sentry from "@sentry/nextjs";
|
||||
import { LayoutDashboard, RefreshCw } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useTranslations } from "next-intl";
|
||||
@@ -22,7 +21,6 @@ export default function AdminErrorPage({
|
||||
|
||||
useEffect(() => {
|
||||
console.error(error);
|
||||
Sentry.captureException(error);
|
||||
}, [error]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import * as Sentry from "@sentry/nextjs";
|
||||
import { Home, RefreshCw } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useTranslations } from "next-intl";
|
||||
@@ -22,7 +21,6 @@ export default function ErrorPage({
|
||||
|
||||
useEffect(() => {
|
||||
console.error(error);
|
||||
Sentry.captureException(error);
|
||||
}, [error]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import * as Sentry from "@sentry/nextjs";
|
||||
import { useEffect } from "react";
|
||||
|
||||
/**
|
||||
@@ -16,7 +15,7 @@ export default function GlobalError({
|
||||
reset: () => void;
|
||||
}) {
|
||||
useEffect(() => {
|
||||
Sentry.captureException(error);
|
||||
console.error(error);
|
||||
}, [error]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -91,14 +91,7 @@ const schema = z
|
||||
REDIS_URL: z.string().optional(),
|
||||
// Logging level.
|
||||
LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).optional(),
|
||||
// Optional Sentry — no-op when unset.
|
||||
SENTRY_DSN: z.string().url().optional().or(z.literal("")),
|
||||
NEXT_PUBLIC_SENTRY_DSN: z.string().url().optional().or(z.literal("")),
|
||||
SENTRY_ORG: z.string().optional(),
|
||||
SENTRY_PROJECT: z.string().optional(),
|
||||
SENTRY_AUTH_TOKEN: z.string().optional(),
|
||||
APP_VERSION: z.string().optional(),
|
||||
NEXT_PUBLIC_APP_VERSION: z.string().optional(),
|
||||
})
|
||||
.superRefine((data, ctx) => {
|
||||
if (data.NODE_ENV !== "production") return;
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import * as Sentry from "@sentry/nextjs";
|
||||
import { redactSentryEvent } from "@/lib/sentry-redact";
|
||||
|
||||
const dsn = process.env.NEXT_PUBLIC_SENTRY_DSN;
|
||||
|
||||
if (dsn) {
|
||||
Sentry.init({
|
||||
dsn,
|
||||
environment: process.env.NODE_ENV,
|
||||
release: process.env.NEXT_PUBLIC_APP_VERSION || process.env.APP_VERSION,
|
||||
tracesSampleRate: process.env.NODE_ENV === "production" ? 0.1 : 1.0,
|
||||
enabled: process.env.NODE_ENV === "production",
|
||||
beforeSend: redactSentryEvent,
|
||||
});
|
||||
}
|
||||
|
||||
export const onRouterTransitionStart = Sentry.captureRouterTransitionStart;
|
||||
@@ -1,12 +0,0 @@
|
||||
import * as Sentry from "@sentry/nextjs";
|
||||
|
||||
export async function register() {
|
||||
if (process.env.NEXT_RUNTIME === "nodejs") {
|
||||
await import("../sentry.server.config");
|
||||
}
|
||||
if (process.env.NEXT_RUNTIME === "edge") {
|
||||
await import("../sentry.edge.config");
|
||||
}
|
||||
}
|
||||
|
||||
export const onRequestError = Sentry.captureRequestError;
|
||||
@@ -6,7 +6,6 @@ const liveVar = "${" + "LIVE}";
|
||||
const stageVar = "${" + "STAGE}";
|
||||
const userVar = "${" + "DEPLOY_USER}";
|
||||
const groupVar = "${" + "DEPLOY_GROUP}";
|
||||
const appVerVar = "${" + "APP_VERSION}";
|
||||
|
||||
function toContainLiteral(workflow: string, literal: string) {
|
||||
return workflow.indexOf(literal) >= 0;
|
||||
@@ -103,15 +102,9 @@ describe("production deploy workflow", () => {
|
||||
expect(deployJob).not.toContain("pnpm test");
|
||||
});
|
||||
|
||||
it("exports APP_VERSION from git for Sentry releases", () => {
|
||||
it("exports APP_VERSION from git for the deployment ID fallback", () => {
|
||||
const exportCmd = `export APP_VERSION="$(git -C "${liveVar}" rev-parse --short origin/main)"`;
|
||||
expect(toContainLiteral(workflow, exportCmd)).toBe(true);
|
||||
expect(
|
||||
toContainLiteral(
|
||||
workflow,
|
||||
`export NEXT_PUBLIC_APP_VERSION="${appVerVar}"`,
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("runs an HTTP health check before declaring deploy success", () => {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { createRequire } from "node:module";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
describe("observability dependency contract", () => {
|
||||
it("does not ship the Sentry SDK", () => {
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
expect(() => require.resolve("@sentry/nextjs")).toThrow();
|
||||
});
|
||||
});
|
||||
@@ -1,8 +1,7 @@
|
||||
import * as Sentry from "@sentry/nextjs";
|
||||
import { logger } from "@/lib/logger";
|
||||
|
||||
/**
|
||||
* Log unexpected errors and forward them to Sentry when a DSN is configured.
|
||||
* Log unexpected errors through the structured application logger.
|
||||
* Domain errors (validation, auth, etc.) should NOT go through here.
|
||||
*/
|
||||
export function reportError(error: unknown, context = "Unhandled error"): void {
|
||||
@@ -11,8 +10,4 @@ export function reportError(error: unknown, context = "Unhandled error"): void {
|
||||
err: message,
|
||||
name: error instanceof Error ? error.name : undefined,
|
||||
});
|
||||
|
||||
if (process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN) {
|
||||
Sentry.captureException(error);
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
import type { ErrorEvent, EventHint } from "@sentry/nextjs";
|
||||
|
||||
const SENSITIVE_KEY_RE =
|
||||
/password|secret|token|otp|recovery|authTicket|two_factor|api_key/i;
|
||||
const REDACTED = "[Redacted]";
|
||||
|
||||
function redactObject(input: unknown, depth = 0): unknown {
|
||||
if (depth > 4 || input == null) return input;
|
||||
if (Array.isArray(input)) return input.map((v) => redactObject(v, depth + 1));
|
||||
if (typeof input !== "object") return input;
|
||||
|
||||
const out: Record<string, unknown> = {};
|
||||
for (const [key, value] of Object.entries(input as Record<string, unknown>)) {
|
||||
if (SENSITIVE_KEY_RE.test(key)) {
|
||||
out[key] = REDACTED;
|
||||
} else {
|
||||
out[key] = redactObject(value, depth + 1);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/** Scrub cookies/auth headers and sensitive keys before sending to Sentry. */
|
||||
export function redactSentryEvent(
|
||||
event: ErrorEvent,
|
||||
_hint: EventHint,
|
||||
): ErrorEvent | null {
|
||||
if (event.request) {
|
||||
if (event.request.cookies) {
|
||||
event.request.cookies =
|
||||
REDACTED as unknown as typeof event.request.cookies;
|
||||
}
|
||||
if (event.request.headers) {
|
||||
const headers = event.request.headers as Record<string, string>;
|
||||
if (headers.cookie) headers.cookie = REDACTED;
|
||||
if (headers.Cookie) headers.Cookie = REDACTED;
|
||||
if (headers.authorization) headers.authorization = REDACTED;
|
||||
if (headers.Authorization) headers.Authorization = REDACTED;
|
||||
}
|
||||
if (event.request.data) {
|
||||
event.request.data = redactObject(
|
||||
event.request.data,
|
||||
) as typeof event.request.data;
|
||||
}
|
||||
}
|
||||
if (event.extra)
|
||||
event.extra = redactObject(event.extra) as typeof event.extra;
|
||||
if (event.contexts) {
|
||||
event.contexts = redactObject(event.contexts) as typeof event.contexts;
|
||||
}
|
||||
return event;
|
||||
}
|
||||
Reference in new issue
Block a user