From 686a0907dbc229d25851fc13e82ebe7f96d9540b Mon Sep 17 00:00:00 2001 From: Real Codesiman Date: Tue, 9 Jun 2026 10:03:28 +0700 Subject: [PATCH] feat(worker): add Sentry error tracking and source maps for debuggable builds Make bundled worker processes debuggable in production by emitting source maps and wiring Sentry to remap and report errors back to TypeScript sources. - Emit source maps from tsdown and run node with --enable-source-maps so stack traces from bundled .mjs map back to the original .ts - Initialize Sentry via instrument.ts loaded with node --import, ahead of every worker; a missing SENTRY_DSN disables it as a no-op - Add sentry helpers (captureException, reportJobFailure, flushSentry) that guard on init, report only final job attempts, and attach identifiers rather than raw job.data to avoid leaking contact PII - Pass debug/observability flags directly in docker-entrypoint so a runtime NODE_OPTIONS cannot clobber them - Document SENTRY_* and WORKER_NAME in .env.example and validate them in env.ts --- .env.example | 15 ++ .../rootfs/usr/local/bin/docker-entrypoint.sh | 19 +- apps/worker/package.json | 1 + apps/worker/src/chat/worker.ts | 4 + apps/worker/src/env.ts | 7 + apps/worker/src/instrument.ts | 33 +++ apps/worker/src/lib/sentry.ts | 85 ++++++++ apps/worker/tsdown.config.ts | 6 +- pnpm-lock.yaml | 190 ++++++++++++++++++ 9 files changed, 356 insertions(+), 4 deletions(-) create mode 100644 apps/worker/src/instrument.ts create mode 100644 apps/worker/src/lib/sentry.ts diff --git a/.env.example b/.env.example index 9ea92ae21..a640168b1 100644 --- a/.env.example +++ b/.env.example @@ -107,3 +107,18 @@ NODE_OPTIONS="--max_old_space_size=4096" # ───────────────────────────────────────────── # Log verbosity: error | warn | info | debug LOG_LEVEL=debug + +# ───────────────────────────────────────────── +# Error tracking (Sentry) +# ───────────────────────────────────────────── +# Leave SENTRY_DSN empty to disable Sentry entirely (no-op). +# Get a DSN from sentry.io → Project Settings → Client Keys (DSN). +SENTRY_DSN= +# Logical environment shown in Sentry (defaults to NODE_ENV). +SENTRY_ENVIRONMENT= +# Release/commit identifier so events are grouped by deploy. Set to the git SHA in CI. +SENTRY_RELEASE= +# Performance tracing sample rate, 0–1. Default 0 (errors only) to protect quota. +SENTRY_TRACES_SAMPLE_RATE=0 +# Identifies which worker process emitted an event (e.g. "worker-chat"). +WORKER_NAME= diff --git a/apps/worker/docker/rootfs/usr/local/bin/docker-entrypoint.sh b/apps/worker/docker/rootfs/usr/local/bin/docker-entrypoint.sh index 6857cac6b..5bd889650 100755 --- a/apps/worker/docker/rootfs/usr/local/bin/docker-entrypoint.sh +++ b/apps/worker/docker/rootfs/usr/local/bin/docker-entrypoint.sh @@ -4,6 +4,14 @@ set -eu WORKER_DIST_DIR="/app/apps/worker/dist" NODE_BIN="/usr/local/bin/node" +INSTRUMENT_SCRIPT="${WORKER_DIST_DIR}/instrument.mjs" +# Debug + observability flags applied to every worker process: +# --enable-source-maps : remap stack traces from bundled .mjs back to .ts +# --import instrument : initialize Sentry before any worker module loads +# Passed directly (not via NODE_OPTIONS) so a runtime NODE_OPTIONS +# (e.g. --max_old_space_size) cannot clobber them. Unquoted on use so it +# word-splits into separate flags. +NODE_FLAGS="--enable-source-maps --import ${INSTRUMENT_SCRIPT}" # ALL_WORKERS="chat integration ai-agent default webhook trigger analytics schedule sequence-scheduler sequence-producer sequence-consumer" ALL_WORKERS="chat integration ai-agent default webhook trigger analytics schedule sequence-scheduler" @@ -76,7 +84,9 @@ run_all_workers() { trap 'handle_shutdown' INT TERM - # Validate all worker entrypoints first so we never start partially. + # Validate the Sentry instrument and all worker entrypoints first so we + # never start partially. + require_script "$INSTRUMENT_SCRIPT" for worker in $ALL_WORKERS; do script="$(resolve_worker_script "$worker")" require_script "$script" @@ -85,7 +95,8 @@ run_all_workers() { for worker in $ALL_WORKERS; do script="$(resolve_worker_script "$worker")" echo "Starting worker: $worker ($script)" - "$NODE_BIN" "$script" & + # shellcheck disable=SC2086 # NODE_FLAGS must word-split into separate flags + "$NODE_BIN" $NODE_FLAGS "$script" & pids="$pids $!" done @@ -128,8 +139,10 @@ case "${1:-}" in print_usage exit 3 } + require_script "$INSTRUMENT_SCRIPT" require_script "$script" - exec "$NODE_BIN" "$script" + # shellcheck disable=SC2086 # NODE_FLAGS must word-split into separate flags + exec "$NODE_BIN" $NODE_FLAGS "$script" ;; "/bin/sh" | "sh" | "/bin/bash" | "bash") exec "$@" diff --git a/apps/worker/package.json b/apps/worker/package.json index f10ee81db..3682ae919 100644 --- a/apps/worker/package.json +++ b/apps/worker/package.json @@ -63,6 +63,7 @@ "@faker-js/faker": "^10.4.0", "@mozilla/readability": "^0.6.0", "@platformatic/kafka": "^1.34.0", + "@sentry/node": "^10.56.0", "@t3-oss/env-core": "^0.13.11", "ai": "^6.0.170", "bullmq": "^5.76.4", diff --git a/apps/worker/src/chat/worker.ts b/apps/worker/src/chat/worker.ts index a02fd83b2..99a731f6f 100644 --- a/apps/worker/src/chat/worker.ts +++ b/apps/worker/src/chat/worker.ts @@ -11,6 +11,7 @@ import { import { type Job, Worker } from "bullmq" import { ensureBootstrapped } from "../lib/bootstrap" import { logger } from "../lib/logger" +import { captureException, flushSentry, reportJobFailure } from "../lib/sentry" import { sendChatMessage, sendFlowStep } from "./handlers/send-flow-step" import { sendMessageToChannel, @@ -25,6 +26,8 @@ async function startChatWorker() { logger.info("Chat worker bootstrapped successfully") } catch (err) { logger.error(err, "Failed to bootstrap chat worker") + captureException(err, { worker: "chat", phase: "bootstrap" }) + await flushSentry() process.exit(1) } @@ -75,6 +78,7 @@ async function startChatWorker() { worker.on("failed", (job, err) => { if (job) { logger.error(err, `Job ${job.id} has failed`) + reportJobFailure(job, err, { worker: "chat" }) } }) } diff --git a/apps/worker/src/env.ts b/apps/worker/src/env.ts index 002742a07..b00d830a4 100644 --- a/apps/worker/src/env.ts +++ b/apps/worker/src/env.ts @@ -9,6 +9,13 @@ export const env = createEnv({ server: { NEXT_PUBLIC_EDITION: editionRule, QUOTA_SYNC_INTERVAL_SECONDS: z.coerce.number().int().min(10).default(60), + // Observability — all optional; omitting SENTRY_DSN disables Sentry. + // Read directly from process.env in instrument.ts (runs before this module). + SENTRY_DSN: z.url().optional(), + SENTRY_ENVIRONMENT: z.string().optional(), + SENTRY_RELEASE: z.string().optional(), + SENTRY_TRACES_SAMPLE_RATE: z.coerce.number().min(0).max(1).optional(), + WORKER_NAME: z.string().optional(), }, runtimeEnv: process.env, skipValidation: process.env.SKIP_ENV_CHECK === "true", diff --git a/apps/worker/src/instrument.ts b/apps/worker/src/instrument.ts new file mode 100644 index 000000000..bbd85cff5 --- /dev/null +++ b/apps/worker/src/instrument.ts @@ -0,0 +1,33 @@ +/** + * Sentry initialization for the worker. + * + * This file MUST be loaded before any other module so Sentry can hook into + * the runtime early. In production it is wired via node's `--import` flag in + * `docker/rootfs/usr/local/bin/docker-entrypoint.sh`, so it runs ahead of every + * worker entrypoint. + * + * It reads configuration straight from `process.env` (not the validated `env` + * module) on purpose: this runs before anything else, and a missing DSN simply + * disables Sentry rather than throwing. + */ +import { init } from "@sentry/node" + +const dsn = process.env.SENTRY_DSN + +if (dsn) { + const tracesSampleRate = process.env.SENTRY_TRACES_SAMPLE_RATE + ? Number(process.env.SENTRY_TRACES_SAMPLE_RATE) + : 0 + + init({ + dsn, + environment: + process.env.SENTRY_ENVIRONMENT ?? process.env.NODE_ENV ?? "development", + release: process.env.SENTRY_RELEASE, + // Errors are the priority. Performance tracing is sampled low (default off) + // to protect the Sentry quota — raise SENTRY_TRACES_SAMPLE_RATE when needed. + tracesSampleRate: Number.isFinite(tracesSampleRate) ? tracesSampleRate : 0, + // Identify which worker process emitted the event (set per container). + serverName: process.env.WORKER_NAME, + }) +} diff --git a/apps/worker/src/lib/sentry.ts b/apps/worker/src/lib/sentry.ts new file mode 100644 index 000000000..248169165 --- /dev/null +++ b/apps/worker/src/lib/sentry.ts @@ -0,0 +1,85 @@ +import { + flush, + getClient, + captureException as sentryCaptureException, +} from "@sentry/node" +import type { Job } from "bullmq" + +/** + * Whether Sentry was initialized (i.e. a DSN was provided). When false, every + * helper below is a cheap no-op, so call sites don't need their own guards. + */ +export function isSentryEnabled(): boolean { + return Boolean(getClient()) +} + +/** + * Capture an arbitrary exception with optional structured context. + * Safe to call even when Sentry is disabled — it just returns. + */ +export function captureException( + err: unknown, + context?: Record, +): void { + if (!isSentryEnabled()) { + return + } + + sentryCaptureException(err, context ? { extra: context } : undefined) +} + +/** + * Report a BullMQ job failure. Only the *final* attempt is sent: a job that + * still has retries left would otherwise emit a duplicate event on every + * attempt and burn through the Sentry quota during a retry storm. + * + * Job payloads can contain contact PII, so only identifiers and retry metadata + * are attached — never the raw `job.data`. + */ +export function reportJobFailure( + job: Job | undefined, + err: unknown, + context: { worker: string }, +): void { + if (!(job && isSentryEnabled())) { + return + } + + const attemptsMade = job.attemptsMade ?? 0 + const maxAttempts = job.opts?.attempts ?? 1 + + // Still has retries left — wait for the final attempt before reporting. + if (attemptsMade < maxAttempts) { + return + } + + sentryCaptureException(err, (scope) => { + scope.setTag("worker", context.worker) + scope.setTag("queue", job.queueName) + scope.setTag("job.name", job.name) + scope.setContext("job", { + id: job.id, + name: job.name, + queue: job.queueName, + attemptsMade, + maxAttempts, + }) + return scope + }) +} + +/** + * Flush queued Sentry events before the process exits. Best-effort: never block + * shutdown if Sentry is slow or unreachable. + */ +export async function flushSentry(timeoutMs = 2000): Promise { + if (!isSentryEnabled()) { + return + } + + try { + await flush(timeoutMs) + } catch { + // ignore — shutdown must not hang on Sentry + } +} diff --git a/apps/worker/tsdown.config.ts b/apps/worker/tsdown.config.ts index d51e2df6b..57bb846c0 100644 --- a/apps/worker/tsdown.config.ts +++ b/apps/worker/tsdown.config.ts @@ -3,6 +3,8 @@ import { defineConfig } from "tsdown" export default defineConfig({ format: ["esm"], entry: [ + // Loaded first via node --import; initializes Sentry before any worker runs. + "src/instrument.ts", "src/chat/worker.ts", "src/integration/worker.ts", "src/ai-agent/worker.ts", @@ -29,6 +31,8 @@ export default defineConfig({ minify: false, unbundle: false, // splitting: false, - sourcemap: false, + // Emit source maps so node --enable-source-maps and Sentry map stack traces + // in the bundled .mjs output back to the original TypeScript sources. + sourcemap: true, treeshake: true, }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b645fee93..d0619bd37 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -655,6 +655,9 @@ importers: '@platformatic/kafka': specifier: ^1.34.0 version: 1.34.0 + '@sentry/node': + specifier: ^10.56.0 + version: 10.56.0 '@t3-oss/env-core': specifier: ^0.13.11 version: 0.13.11(typescript@5.9.3)(zod@4.4.3) @@ -4371,10 +4374,38 @@ packages: '@open-draft/until@2.1.0': resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} + '@opentelemetry/api-logs@0.214.0': + resolution: {integrity: sha512-40lSJeqYO8Uz2Yj7u94/SJWE/wONa7rmMKjI1ZcIjgf3MHNHv1OZUCrCETGuaRF62d5pQD1wKIW+L4lmSMTzZA==} + engines: {node: '>=8.0.0'} + '@opentelemetry/api@1.9.1': resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==} engines: {node: '>=8.0.0'} + '@opentelemetry/core@2.7.1': + resolution: {integrity: sha512-QAqIj32AtK6+pEVNG7EOVxHdE06RP+FM5qpiEJ4RtDcFIqKUZHYhl7/7UY5efhwmwNAg7j8QbJVBLxMerc0+gw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/instrumentation@0.214.0': + resolution: {integrity: sha512-MHqEX5Dk59cqVah5LiARMACku7jXSVk9iVDWOea4x3cr7VfdByeDCURK6o1lntT1JS/Tsovw01UJrBhN3/uC5w==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/resources@2.7.1': + resolution: {integrity: sha512-DeT6KKolmC4e/dRQvMQ/RwlnzhaqeiFOXY5ngoOPJ07GgVVKxZOg9EcrNZb5aTzUn+iCrJldAgOfQm1O/QfPAQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/sdk-trace-base@2.7.1': + resolution: {integrity: sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + '@opentelemetry/semantic-conventions@1.41.1': resolution: {integrity: sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==} engines: {node: '>=14'} @@ -5852,6 +5883,51 @@ packages: peerDependencies: selderee: ~0.12.0 + '@sentry-internal/server-utils@10.56.0': + resolution: {integrity: sha512-6kuZI/vAjyVKMm1cTzc2pdUmVR4Px4etMG6wnCPyFnwEaGbUKQnTynUBFpTuo/q6Js6QBQvhLNoAnO4YsOfW4w==} + engines: {node: '>=18'} + + '@sentry/core@10.56.0': + resolution: {integrity: sha512-L+u1dIz5SANrmST5jhIwETtt4apILgKrylv12X4hKJU0PvZl+NorjeV/ty3MwzpKQPg6b6q6qMOSLc1rLpy3iQ==} + engines: {node: '>=18'} + + '@sentry/node-core@10.56.0': + resolution: {integrity: sha512-61lD2Wjtv5Lw2F3lJarcD0ORjR4GlVxrEd6w6Of/uF3DH73dD6K3n/3wXEeCIRfV/kgiCFIrCIq76nz0LVgE5g==} + engines: {node: '>=18'} + peerDependencies: + '@opentelemetry/api': ^1.9.0 + '@opentelemetry/core': ^1.30.1 || ^2.1.0 + '@opentelemetry/exporter-trace-otlp-http': '>=0.57.0 <1' + '@opentelemetry/instrumentation': '>=0.57.1 <1' + '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 + '@opentelemetry/semantic-conventions': ^1.39.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@opentelemetry/core': + optional: true + '@opentelemetry/exporter-trace-otlp-http': + optional: true + '@opentelemetry/instrumentation': + optional: true + '@opentelemetry/sdk-trace-base': + optional: true + '@opentelemetry/semantic-conventions': + optional: true + + '@sentry/node@10.56.0': + resolution: {integrity: sha512-qvgtXHkcR4CH3fh0VEVyw4Ysc6MMiAnm727NdTTm0yU5e53erCeo2521+yfJkqmRTGiOSgwA7B5Bs+ot9j0vFQ==} + engines: {node: '>=18'} + + '@sentry/opentelemetry@10.56.0': + resolution: {integrity: sha512-PtMudApHMHvttjos3b7JZ2gJ+nstHAOYE3vKPYB5o0WQO95ldiaYnpLKMCRIGZWF3Dk7ynrqqnBpn8LZLt+Mrg==} + engines: {node: '>=18'} + peerDependencies: + '@opentelemetry/api': ^1.9.0 + '@opentelemetry/core': ^1.30.1 || ^2.1.0 + '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 + '@opentelemetry/semantic-conventions': ^1.39.0 + '@smithy/core@3.24.6': resolution: {integrity: sha512-wBXDRup6UU97VKyaiRo8AssnfStPtG0oAAfpq/bC0a1YYau8pM86YB4kM6ccoVi1mS8l/UHbn9oDM+7uozr/ug==} engines: {node: '>=18.0.0'} @@ -6642,6 +6718,11 @@ packages: resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} engines: {node: '>= 0.6'} + acorn-import-attributes@1.9.5: + resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} + peerDependencies: + acorn: ^8 + acorn-jsx-walk@2.0.0: resolution: {integrity: sha512-uuo6iJj4D4ygkdzd6jPtcxs8vZgDX9YFIkqczGImoypX2fQ4dVImmu3UzA4ynixCIMTrEOWW+95M2HuBaCEOVA==} @@ -6979,6 +7060,9 @@ packages: citty@0.2.2: resolution: {integrity: sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==} + cjs-module-lexer@2.2.0: + resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==} + class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} @@ -8208,6 +8292,10 @@ packages: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} + import-in-the-middle@3.0.2: + resolution: {integrity: sha512-LGLYRl0A2gtyUJb2WDliBHmk6TtlHwdDjxonacZ8QrEs/ZW+YDgNv2QAfjRQWpS8HqvNcq6GGnN6jrOa5FysDQ==} + engines: {node: '>=18'} + import-without-cache@0.3.3: resolution: {integrity: sha512-bDxwDdF04gm550DfZHgffvlX+9kUlcz32UD0AeBTmVPFiWkrexF2XVmiuFFbDhiFuP8fQkrkvI2KdSNPYWAXkQ==} engines: {node: '>=20.19.0'} @@ -8918,6 +9006,9 @@ packages: mnemonist@0.40.4: resolution: {integrity: sha512-ZAv+KNavneRVzu4tUeOgzkScI3W5BGwZ3rkxIpKtzzVgfTtWQFN1CgX0U72cyvyh3iTuHL3SiSmrQxTlryEIcw==} + module-details-from-path@1.0.4: + resolution: {integrity: sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==} + motion-dom@12.40.0: resolution: {integrity: sha512-HxU3ZaBwNPVQUBQf1xxgq+7JrPNZvjLVxgbpEZL7RrWJnsxOf0/OM+yrHG9ogLQ31Do/r57Oz2gQWPK+6q62mg==} @@ -9908,6 +9999,10 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + require-in-the-middle@8.0.1: + resolution: {integrity: sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ==} + engines: {node: '>=9.3.0 || >=8.10.0 <9.0.0'} + reselect@5.1.1: resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==} @@ -12676,8 +12771,39 @@ snapshots: '@open-draft/until@2.1.0': {} + '@opentelemetry/api-logs@0.214.0': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api@1.9.1': {} + '@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/semantic-conventions': 1.41.1 + + '@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.214.0 + import-in-the-middle: 3.0.2 + require-in-the-middle: 8.0.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/resources@2.7.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.41.1 + + '@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.41.1 + '@opentelemetry/semantic-conventions@1.41.1': {} '@orpc/client@1.14.4(@opentelemetry/api@1.9.1)': @@ -14044,6 +14170,48 @@ snapshots: domhandler: 5.0.3 selderee: 0.12.0 + '@sentry-internal/server-utils@10.56.0': + dependencies: + '@sentry/core': 10.56.0 + + '@sentry/core@10.56.0': {} + + '@sentry/node-core@10.56.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.41.1)': + dependencies: + '@sentry/core': 10.56.0 + '@sentry/opentelemetry': 10.56.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.41.1) + import-in-the-middle: 3.0.2 + optionalDependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.41.1 + + '@sentry/node@10.56.0': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.41.1 + '@sentry-internal/server-utils': 10.56.0 + '@sentry/core': 10.56.0 + '@sentry/node-core': 10.56.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.41.1) + '@sentry/opentelemetry': 10.56.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.41.1) + import-in-the-middle: 3.0.2 + transitivePeerDependencies: + - '@opentelemetry/exporter-trace-otlp-http' + - supports-color + + '@sentry/opentelemetry@10.56.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.41.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.41.1 + '@sentry/core': 10.56.0 + '@smithy/core@3.24.6': dependencies: '@aws-crypto/crc32': 5.2.0 @@ -14843,6 +15011,10 @@ snapshots: mime-types: 3.0.2 negotiator: 1.0.0 + acorn-import-attributes@1.9.5(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + acorn-jsx-walk@2.0.0: {} acorn-jsx@5.3.2(acorn@8.16.0): @@ -15152,6 +15324,8 @@ snapshots: citty@0.2.2: {} + cjs-module-lexer@2.2.0: {} + class-variance-authority@0.7.1: dependencies: clsx: 2.1.1 @@ -16388,6 +16562,13 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 + import-in-the-middle@3.0.2: + dependencies: + acorn: 8.16.0 + acorn-import-attributes: 1.9.5(acorn@8.16.0) + cjs-module-lexer: 2.2.0 + module-details-from-path: 1.0.4 + import-without-cache@0.3.3: {} index-to-position@1.2.0: {} @@ -17429,6 +17610,8 @@ snapshots: dependencies: obliterator: 2.0.5 + module-details-from-path@1.0.4: {} + motion-dom@12.40.0: dependencies: motion-utils: 12.39.0 @@ -18527,6 +18710,13 @@ snapshots: require-from-string@2.0.2: {} + require-in-the-middle@8.0.1: + dependencies: + debug: 4.4.3(supports-color@10.2.2) + module-details-from-path: 1.0.4 + transitivePeerDependencies: + - supports-color + reselect@5.1.1: {} resize-observer-polyfill@1.5.1: {}