mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
fix: error-only Sentry telemetry, storm-proof capture, and crash fixes (#476)
Removes Sentry tracing entirely (BullMQ idle polling burned 4.8M transactions in 2 days at the baked 0.1 rate), decouples PostHog sampling, and replaces the type-only error scrub with a vetted-field sanitizer plus SafeError/ToolInputError contracts. One classified capture path with per-signature throttles and a per-process ceiling makes storms impossible (NODE-1E was 4,541 events from one 30s loop). Browser errors move to a dedicated web Sentry project with their own source maps. Adds the SNAPOTTER_TELEMETRY runtime kill switch and silences test fleets. Crash fixes: remote 204/304 SSRF process kill (NODE-20), conversion-preset boot crash loop (NODE-21), Redis version preflight + unhandled subscribe rejection (NODE-1T), Sign PDF on plain-http origins (NODE-1K/1M), wavesurfer/pdf.js teardown rejections (NODE-1P/1N), bundle-import ZlibError to 400 (NODE-1Z), chart-maker input errors declassified (NODE-1H/1J), asset requests skip the session DB lookup (NODE-1D).
This commit is contained in:
+20
-4
@@ -5,21 +5,22 @@ import cors from "@fastify/cors";
|
||||
import rateLimit from "@fastify/rate-limit";
|
||||
import { trace } from "@opentelemetry/api";
|
||||
import { getDispatcherStatus, initDispatcher, isGpuAvailable } from "@snapotter/ai";
|
||||
import { APP_VERSION } from "@snapotter/shared";
|
||||
import { APP_VERSION, SafeError } from "@snapotter/shared";
|
||||
import { eq, sql } from "drizzle-orm";
|
||||
import Fastify from "fastify";
|
||||
import { env } from "./config.js";
|
||||
import { closeDb, db, schema } from "./db/index.js";
|
||||
import { runMigrations } from "./db/migrate.js";
|
||||
import { startCancelListener, stopCancelListener } from "./jobs/cancel.js";
|
||||
import { closeRedis, pingRedis } from "./jobs/connection.js";
|
||||
import { assertRedisCompatible, closeRedis, pingRedis } from "./jobs/connection.js";
|
||||
import { closeFlowProducer, closeQueueEvents, warmQueueEvents } from "./jobs/enqueue.js";
|
||||
import { closeQueues, perPoolHealth, queueCounts } from "./jobs/queues.js";
|
||||
import { enqueueSystemJob, SYSTEM_JOBS, scheduleSystemJobs } from "./jobs/system-jobs.js";
|
||||
import { closeWorkers, startWorkers } from "./jobs/worker.js";
|
||||
import { captureException, initAnalytics, shutdownAnalytics } from "./lib/analytics.js";
|
||||
import { initAnalytics, shutdownAnalytics } from "./lib/analytics.js";
|
||||
import { shouldRunStartupCleanup } from "./lib/cleanup.js";
|
||||
import { buildCsp } from "./lib/csp.js";
|
||||
import { reportError } from "./lib/error-report.js";
|
||||
import { stripInternalPaths } from "./lib/errors.js";
|
||||
import { ensureAiDirs, recoverInterruptedInstalls } from "./lib/feature-status.js";
|
||||
import { logger } from "./lib/logger.js";
|
||||
@@ -89,6 +90,16 @@ try {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// BullMQ v5 requires Redis >= 6.2. Fail fast with an actionable message instead
|
||||
// of crash-looping later on ReplyErrors from an incompatible server.
|
||||
try {
|
||||
await assertRedisCompatible();
|
||||
} catch (err) {
|
||||
const detected = err instanceof SafeError && err.code ? ` (detected ${err.code})` : "";
|
||||
console.error(`FATAL: ${(err as Error).message}${detected}`);
|
||||
process.exit(1);
|
||||
}
|
||||
console.log("Redis connected");
|
||||
|
||||
// Verify the local storage directories are writable before serving. A non-root
|
||||
@@ -276,7 +287,12 @@ app.setErrorHandler((error: Error & { statusCode?: number }, request, reply) =>
|
||||
{ err: error, url: request.url, method: request.method },
|
||||
"Unhandled request error",
|
||||
);
|
||||
captureException(error);
|
||||
void reportError(error, {
|
||||
source: "http",
|
||||
route: request.routeOptions?.url ?? undefined,
|
||||
method: request.method,
|
||||
statusCode,
|
||||
});
|
||||
} else {
|
||||
request.log.warn({ err: error, url: request.url, method: request.method }, "Request error");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user