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
-3
@@ -70,7 +70,5 @@ PAYPAL_CLIENT_ID=
|
|||||||
PAYPAL_SECRET=
|
PAYPAL_SECRET=
|
||||||
PAYPAL_API=https://api-m.sandbox.paypal.com
|
PAYPAL_API=https://api-m.sandbox.paypal.com
|
||||||
|
|
||||||
# --- LOGGING & SENTRY (Zod-Proof Dummy URLs) ---
|
# --- LOGGING ---
|
||||||
LOG_LEVEL=error
|
LOG_LEVEL=error
|
||||||
SENTRY_DSN=https://[email protected]/0
|
|
||||||
NEXT_PUBLIC_SENTRY_DSN=https://[email protected]/0
|
|
||||||
@@ -105,7 +105,6 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
export APP_VERSION="$(git -C "${LIVE}" rev-parse --short origin/main)"
|
export APP_VERSION="$(git -C "${LIVE}" rev-parse --short origin/main)"
|
||||||
export NEXT_PUBLIC_APP_VERSION="${APP_VERSION}"
|
|
||||||
echo "APP_VERSION=${APP_VERSION}"
|
echo "APP_VERSION=${APP_VERSION}"
|
||||||
|
|
||||||
STAGE="/var/tmp/atom-nexst-stage-${APP_VERSION}"
|
STAGE="/var/tmp/atom-nexst-stage-${APP_VERSION}"
|
||||||
|
|||||||
@@ -4,8 +4,7 @@
|
|||||||
"src/app/**/page.{ts,tsx}",
|
"src/app/**/page.{ts,tsx}",
|
||||||
"src/app/**/layout.{ts,tsx}",
|
"src/app/**/layout.{ts,tsx}",
|
||||||
"src/app/**/route.{ts,tsx}",
|
"src/app/**/route.{ts,tsx}",
|
||||||
"src/app/**/{error,not-found,loading,template,default,global-error}.{ts,tsx}",
|
"src/app/**/{error,not-found,loading,template,default,global-error}.{ts,tsx}"
|
||||||
"sentry.{server,edge}.config.ts"
|
|
||||||
],
|
],
|
||||||
"project": ["src/**/*.{ts,tsx}"],
|
"project": ["src/**/*.{ts,tsx}"],
|
||||||
"ignoreDependencies": [
|
"ignoreDependencies": [
|
||||||
|
|||||||
+1
-22
@@ -1,6 +1,5 @@
|
|||||||
import { execFileSync } from "node:child_process";
|
import { execFileSync } from "node:child_process";
|
||||||
import withBundleAnalyzer from "@next/bundle-analyzer";
|
import withBundleAnalyzer from "@next/bundle-analyzer";
|
||||||
import { withSentryConfig } from "@sentry/nextjs";
|
|
||||||
import type { NextConfig } from "next";
|
import type { NextConfig } from "next";
|
||||||
import createNextIntlPlugin from "next-intl/plugin";
|
import createNextIntlPlugin from "next-intl/plugin";
|
||||||
|
|
||||||
@@ -82,28 +81,8 @@ const withNextIntl = createNextIntlPlugin("./src/i18n/request.ts");
|
|||||||
|
|
||||||
const config = withNextIntl(nextConfig);
|
const config = withNextIntl(nextConfig);
|
||||||
|
|
||||||
// Source-map upload + release creation need SENTRY_AUTH_TOKEN.
|
|
||||||
// Without it, keep the SDK wrapper but skip remote Sentry build steps
|
|
||||||
// so CI/prod compile stays quiet (runtime DSN still works independently).
|
|
||||||
const sentryAuthToken = process.env.SENTRY_AUTH_TOKEN;
|
|
||||||
|
|
||||||
const withBA = withBundleAnalyzer({
|
const withBA = withBundleAnalyzer({
|
||||||
enabled: process.env.ANALYZE === "true",
|
enabled: process.env.ANALYZE === "true",
|
||||||
});
|
});
|
||||||
|
|
||||||
export default withBA(
|
export default withBA(config);
|
||||||
withSentryConfig(config, {
|
|
||||||
org: process.env.SENTRY_ORG,
|
|
||||||
project: process.env.SENTRY_PROJECT,
|
|
||||||
authToken: sentryAuthToken,
|
|
||||||
silent: !process.env.CI || !sentryAuthToken,
|
|
||||||
widenClientFileUpload: true,
|
|
||||||
sourcemaps: {
|
|
||||||
disable: !sentryAuthToken,
|
|
||||||
},
|
|
||||||
release: {
|
|
||||||
create: Boolean(sentryAuthToken),
|
|
||||||
},
|
|
||||||
telemetry: false,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
@@ -40,7 +40,6 @@
|
|||||||
"@dnd-kit/sortable": "^10.0.0",
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
"@dnd-kit/utilities": "^3.2.2",
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
"@hookform/resolvers": "^5.5.7",
|
"@hookform/resolvers": "^5.5.7",
|
||||||
"@sentry/nextjs": "^10.69.0",
|
|
||||||
"@tanstack/react-virtual": "^3.14.9",
|
"@tanstack/react-virtual": "^3.14.9",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
|||||||
Generated
+36
-1762
File diff suppressed because it is too large.
Load diff
+1
-2
@@ -6,7 +6,6 @@ allowBuilds:
|
|||||||
sharp: true
|
sharp: true
|
||||||
"@parcel/watcher": true
|
"@parcel/watcher": true
|
||||||
"@swc/core": true
|
"@swc/core": true
|
||||||
"@sentry/cli": true
|
|
||||||
bcrypt: true
|
bcrypt: true
|
||||||
|
|
||||||
# Al jouw overrides netjes bij elkaar inclusief de nieuwe security patches
|
# Al jouw overrides netjes bij elkaar inclusief de nieuwe security patches
|
||||||
@@ -29,4 +28,4 @@ peerDependencyRules:
|
|||||||
allowedVersions:
|
allowedVersions:
|
||||||
nodemailer: "9.0.3"
|
nodemailer: "9.0.3"
|
||||||
ignoreMissing:
|
ignoreMissing:
|
||||||
- nodemailer
|
- nodemailer
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import * as Sentry from "@sentry/nextjs";
|
|
||||||
import { Cron } from "croner";
|
import { Cron } from "croner";
|
||||||
import { lt, sql } from "drizzle-orm";
|
import { lt, sql } from "drizzle-orm";
|
||||||
import { env } from "../src/env";
|
import { env } from "../src/env";
|
||||||
@@ -8,27 +7,11 @@ import { redis } from "../src/lib/redis";
|
|||||||
import { emulatorOffline, healthDegraded } from "../src/lib/services/alert";
|
import { emulatorOffline, healthDegraded } from "../src/lib/services/alert";
|
||||||
import { rcon } from "../src/lib/services/rcon";
|
import { rcon } from "../src/lib/services/rcon";
|
||||||
|
|
||||||
function initWorkerSentry(): void {
|
|
||||||
const dsn = process.env.SENTRY_DSN;
|
|
||||||
if (!dsn || process.env.NODE_ENV !== "production") return;
|
|
||||||
|
|
||||||
Sentry.init({
|
|
||||||
dsn,
|
|
||||||
environment: process.env.NODE_ENV,
|
|
||||||
release: process.env.APP_VERSION,
|
|
||||||
tracesSampleRate: 0.05,
|
|
||||||
});
|
|
||||||
logger.info("Sentry initialized for jobs worker", { module: "jobs" });
|
|
||||||
}
|
|
||||||
|
|
||||||
function captureWorkerError(err: unknown, context: string): void {
|
function captureWorkerError(err: unknown, context: string): void {
|
||||||
logger.error(context, {
|
logger.error(context, {
|
||||||
module: "jobs",
|
module: "jobs",
|
||||||
err: err instanceof Error ? err.message : String(err),
|
err: err instanceof Error ? err.message : String(err),
|
||||||
});
|
});
|
||||||
if (process.env.SENTRY_DSN) {
|
|
||||||
Sentry.captureException(err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** In-process cooldown so a flapping probe does not spam Discord/email. */
|
/** In-process cooldown so a flapping probe does not spam Discord/email. */
|
||||||
@@ -241,7 +224,6 @@ async function cleanupOldSessions(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
initWorkerSentry();
|
|
||||||
logger.info("Worker started", { module: "jobs" });
|
logger.info("Worker started", { module: "jobs" });
|
||||||
|
|
||||||
if (env.EMULATOR_JAR_PATH && env.EMULATOR_BACKUP_DIR) {
|
if (env.EMULATOR_JAR_PATH && env.EMULATOR_BACKUP_DIR) {
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
import * as Sentry from "@sentry/nextjs";
|
|
||||||
import { redactSentryEvent } from "@/lib/sentry-redact";
|
|
||||||
|
|
||||||
const dsn = process.env.SENTRY_DSN;
|
|
||||||
|
|
||||||
if (dsn) {
|
|
||||||
Sentry.init({
|
|
||||||
dsn,
|
|
||||||
environment: process.env.NODE_ENV,
|
|
||||||
release: process.env.APP_VERSION,
|
|
||||||
tracesSampleRate: process.env.NODE_ENV === "production" ? 0.1 : 1.0,
|
|
||||||
enabled: process.env.NODE_ENV === "production",
|
|
||||||
ignoreErrors: ["AbortError", "NEXT_REDIRECT", "NEXT_NOT_FOUND"],
|
|
||||||
beforeSend: redactSentryEvent,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import * as Sentry from "@sentry/nextjs";
|
|
||||||
import { redactSentryEvent } from "@/lib/sentry-redact";
|
|
||||||
|
|
||||||
const dsn = process.env.SENTRY_DSN;
|
|
||||||
|
|
||||||
if (dsn) {
|
|
||||||
Sentry.init({
|
|
||||||
dsn,
|
|
||||||
environment: process.env.NODE_ENV,
|
|
||||||
release: process.env.APP_VERSION,
|
|
||||||
tracesSampleRate: process.env.NODE_ENV === "production" ? 0.1 : 1.0,
|
|
||||||
enabled: process.env.NODE_ENV === "production",
|
|
||||||
ignoreErrors: [
|
|
||||||
"Network request failed",
|
|
||||||
"AbortError",
|
|
||||||
"NEXT_REDIRECT",
|
|
||||||
"NEXT_NOT_FOUND",
|
|
||||||
"UnrecognizedActionError",
|
|
||||||
"Server Action.*was not found on the server",
|
|
||||||
],
|
|
||||||
beforeSend: redactSentryEvent,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import * as Sentry from "@sentry/nextjs";
|
|
||||||
import { Home, RefreshCw } from "lucide-react";
|
import { Home, RefreshCw } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
@@ -22,7 +21,6 @@ export default function SiteErrorPage({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
Sentry.captureException(error);
|
|
||||||
}, [error]);
|
}, [error]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import * as Sentry from "@sentry/nextjs";
|
|
||||||
import { LayoutDashboard, RefreshCw } from "lucide-react";
|
import { LayoutDashboard, RefreshCw } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
@@ -22,7 +21,6 @@ export default function AdminErrorPage({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
Sentry.captureException(error);
|
|
||||||
}, [error]);
|
}, [error]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import * as Sentry from "@sentry/nextjs";
|
|
||||||
import { Home, RefreshCw } from "lucide-react";
|
import { Home, RefreshCw } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
@@ -22,7 +21,6 @@ export default function ErrorPage({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
Sentry.captureException(error);
|
|
||||||
}, [error]);
|
}, [error]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import * as Sentry from "@sentry/nextjs";
|
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -16,7 +15,7 @@ export default function GlobalError({
|
|||||||
reset: () => void;
|
reset: () => void;
|
||||||
}) {
|
}) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Sentry.captureException(error);
|
console.error(error);
|
||||||
}, [error]);
|
}, [error]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -91,14 +91,7 @@ const schema = z
|
|||||||
REDIS_URL: z.string().optional(),
|
REDIS_URL: z.string().optional(),
|
||||||
// Logging level.
|
// Logging level.
|
||||||
LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).optional(),
|
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(),
|
APP_VERSION: z.string().optional(),
|
||||||
NEXT_PUBLIC_APP_VERSION: z.string().optional(),
|
|
||||||
})
|
})
|
||||||
.superRefine((data, ctx) => {
|
.superRefine((data, ctx) => {
|
||||||
if (data.NODE_ENV !== "production") return;
|
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 stageVar = "${" + "STAGE}";
|
||||||
const userVar = "${" + "DEPLOY_USER}";
|
const userVar = "${" + "DEPLOY_USER}";
|
||||||
const groupVar = "${" + "DEPLOY_GROUP}";
|
const groupVar = "${" + "DEPLOY_GROUP}";
|
||||||
const appVerVar = "${" + "APP_VERSION}";
|
|
||||||
|
|
||||||
function toContainLiteral(workflow: string, literal: string) {
|
function toContainLiteral(workflow: string, literal: string) {
|
||||||
return workflow.indexOf(literal) >= 0;
|
return workflow.indexOf(literal) >= 0;
|
||||||
@@ -103,15 +102,9 @@ describe("production deploy workflow", () => {
|
|||||||
expect(deployJob).not.toContain("pnpm test");
|
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)"`;
|
const exportCmd = `export APP_VERSION="$(git -C "${liveVar}" rev-parse --short origin/main)"`;
|
||||||
expect(toContainLiteral(workflow, exportCmd)).toBe(true);
|
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", () => {
|
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";
|
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.
|
* Domain errors (validation, auth, etc.) should NOT go through here.
|
||||||
*/
|
*/
|
||||||
export function reportError(error: unknown, context = "Unhandled error"): void {
|
export function reportError(error: unknown, context = "Unhandled error"): void {
|
||||||
@@ -11,8 +10,4 @@ export function reportError(error: unknown, context = "Unhandled error"): void {
|
|||||||
err: message,
|
err: message,
|
||||||
name: error instanceof Error ? error.name : undefined,
|
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