@quatronic/sdk 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -29,7 +29,7 @@ import { hostname } from "os";
|
|
|
29
29
|
// package.json
|
|
30
30
|
var package_default = {
|
|
31
31
|
name: "@quatronic/sdk",
|
|
32
|
-
version: "0.3.
|
|
32
|
+
version: "0.3.1",
|
|
33
33
|
type: "module",
|
|
34
34
|
private: false,
|
|
35
35
|
publishConfig: {
|
|
@@ -439,4 +439,4 @@ function startNodeSdk(opts) {
|
|
|
439
439
|
export {
|
|
440
440
|
startNodeSdk
|
|
441
441
|
};
|
|
442
|
-
//# sourceMappingURL=chunk-
|
|
442
|
+
//# sourceMappingURL=chunk-WZ4LQM56.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/observability-core/start-node-sdk.ts","../src/observability-core/resource.ts","../package.json","../src/observability-core/noise-filter.ts","../src/observability-core/http-sanitize.ts","../src/observability-core/span-scrub.ts","../src/observability-core/scrub-span-processor.ts","../src/observability-core/format-fatal.ts"],"sourcesContent":["// Shared NodeSDK bootstrap for every server runtime (Next and plain Node). The\n// only per-runtime difference is the noise-prefix list. Importing this module's\n// caller (a register entry) must happen before pino/node:http are first imported\n// so the instrumentations can patch them.\nimport { NodeSDK } from \"@opentelemetry/sdk-node\"\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-http\"\nimport { OTLPMetricExporter } from \"@opentelemetry/exporter-metrics-otlp-http\"\nimport { OTLPLogExporter } from \"@opentelemetry/exporter-logs-otlp-http\"\nimport { PeriodicExportingMetricReader } from \"@opentelemetry/sdk-metrics\"\nimport { BatchLogRecordProcessor } from \"@opentelemetry/sdk-logs\"\nimport { BatchSpanProcessor } from \"@opentelemetry/sdk-trace-base\"\nimport { HttpInstrumentation } from \"@opentelemetry/instrumentation-http\"\nimport { UndiciInstrumentation } from \"@opentelemetry/instrumentation-undici\"\nimport { PinoInstrumentation } from \"@opentelemetry/instrumentation-pino\"\nimport { PgInstrumentation } from \"@opentelemetry/instrumentation-pg\"\nimport { buildResource } from \"./resource\"\nimport { qdcSanitizeHttp, qdcTracesSampleRatio, qdcEnhancedDbReporting, qdcHealthPath } from \"./env\"\nimport { shouldIgnoreIncoming, shouldIgnoreOutgoing } from \"./noise-filter\"\nimport { sanitizeHttpSpanAttributes } from \"./http-sanitize\"\nimport { ScrubSpanProcessor } from \"./scrub-span-processor\"\nimport { formatFatal } from \"./format-fatal\"\n\nexport interface StartNodeSdkOptions {\n noisePrefixes: string[]\n}\n\nexport function startNodeSdk(opts: StartNodeSdkOptions): NodeSDK {\n const { noisePrefixes } = opts\n\n // Sampling defaults before NodeSDK reads env. Default 100% in all envs; an\n // explicit OTEL_TRACES_SAMPLER always wins.\n if (!process.env.OTEL_TRACES_SAMPLER) process.env.OTEL_TRACES_SAMPLER = \"parentbased_traceidratio\"\n if (!process.env.OTEL_TRACES_SAMPLER_ARG) process.env.OTEL_TRACES_SAMPLER_ARG = qdcTracesSampleRatio()\n\n const healthPath = qdcHealthPath()\n\n const httpInstrumentation = new HttpInstrumentation({\n ignoreIncomingRequestHook: (req) => shouldIgnoreIncoming(req, { healthPath, noisePrefixes }),\n ignoreOutgoingRequestHook: (req) => shouldIgnoreOutgoing({ path: req.path ?? undefined }, { healthPath, noisePrefixes }),\n ...(qdcSanitizeHttp()\n ? { requestHook: (span, request) => sanitizeHttpSpanAttributes(span, request as { url?: string; path?: string }) }\n : {}),\n })\n\n // Cross-module / cross-service propagation: global fetch (undici) is the natural\n // way a Next server and a Node backend call CONN_<ALIAS>_URL. instrumentation-http\n // does NOT see undici, so without this the traceparent is never injected and the\n // hop starts a new trace. Injection is unconditional on origin (server-to-server,\n // no CORS) — that is what continues the trace across modules.\n const undiciInstrumentation = new UndiciInstrumentation({\n ignoreRequestHook: (request) =>\n shouldIgnoreOutgoing({ path: (request as { path?: string }).path }, { healthPath, noisePrefixes }),\n ...(qdcSanitizeHttp()\n ? { requestHook: (span, request) =>\n sanitizeHttpSpanAttributes(span, { path: (request as { path?: string }).path }, \"stable\") }\n : {}),\n })\n\n // DB spans. Full SQL + values only off-prod (synthetic data); parametrized only\n // in prod-like envs. `requireParentSpan` drops queries that run with no active\n // parent span — connection-pool warmup, keepalive pings, startup/migration — so\n // each no longer surfaces as its own root trace. Queries inside an HTTP request\n // (or an `observe()` wrapper) still nest under that span and are kept.\n const pgInstrumentation = new PgInstrumentation({\n enhancedDatabaseReporting: qdcEnhancedDbReporting(),\n requireParentSpan: true,\n })\n\n let sdk: NodeSDK\n try {\n sdk = new NodeSDK({\n resource: buildResource(),\n spanProcessors: [new ScrubSpanProcessor(new BatchSpanProcessor(new OTLPTraceExporter()))],\n metricReader: new PeriodicExportingMetricReader({ exporter: new OTLPMetricExporter() }),\n logRecordProcessor: new BatchLogRecordProcessor(new OTLPLogExporter()),\n instrumentations: [httpInstrumentation, undiciInstrumentation, pgInstrumentation, new PinoInstrumentation()],\n })\n } catch (err: unknown) {\n process.stderr.write(`[qdc-sdk] initialization failed: ${err}\\n`)\n process.exit(1)\n }\n\n try {\n sdk.start()\n } catch (err: unknown) {\n process.stderr.write(`[qdc-sdk] SDK start failed: ${err}\\n`)\n process.exit(1)\n }\n\n const gracefulShutdown = async (signal: string): Promise<void> => {\n process.stderr.write(`[qdc-sdk] ${signal} received, shutting down\\n`)\n try { await sdk.shutdown() } catch { /* ignore */ }\n process.exit(0)\n }\n process.on(\"SIGTERM\", () => void gracefulShutdown(\"SIGTERM\"))\n process.on(\"SIGINT\", () => void gracefulShutdown(\"SIGINT\"))\n process.on(\"uncaughtException\", async (err) => {\n process.stderr.write(`[qdc-sdk] fatal: ${formatFatal(err)}\\n`)\n try { await sdk.shutdown() } finally { process.exit(1) }\n })\n process.on(\"unhandledRejection\", async (reason) => {\n process.stderr.write(`[qdc-sdk] fatal: ${formatFatal(reason)}\\n`)\n try { await sdk.shutdown() } finally { process.exit(1) }\n })\n\n return sdk\n}\n","import { type Resource, resourceFromAttributes } from \"@opentelemetry/resources\"\nimport { hostname } from \"node:os\"\nimport { qdcAppId, qdcCustomerId, qdcEnv, qdcModule } from \"./env\"\nimport pkg from \"../../package.json\" with { type: \"json\" }\n\nconst SDK_VERSION = (pkg as { version: string }).version\n\n/**\n * Maps the QDC identity env vars to the OpenTelemetry resource attributes used\n * by the SDK's server-side observability. The NodeSDK carries this resource on\n * every span and log record (the latter via the in-process PinoInstrumentation),\n * so it is the single source of truth for tenant labels.\n *\n * Identity is read from NEXT_PUBLIC_QDC_* with a fallback to legacy QDC_* (see\n * ./env). Throws if the customer or app id are missing — required to land logs\n * and traces under the correct tenant namespace.\n */\nexport function buildResourceAttributes(): Record<string, string> {\n const customerId = qdcCustomerId()\n if (!customerId)\n throw new Error(\"NEXT_PUBLIC_QDC_CUSTOMER_ID (or legacy QDC_CUSTOMER_ID) env var is required\")\n\n const appId = qdcAppId()\n if (!appId)\n throw new Error(\"NEXT_PUBLIC_QDC_APP_ID (or legacy QDC_APP_ID) env var is required\")\n\n const env = qdcEnv()\n\n const attrs: Record<string, string> = {\n \"service.name\": appId,\n \"service.namespace\": customerId,\n \"deployment.environment\": env,\n \"host.name\": hostname(),\n \"qdc.customer_id\": customerId,\n \"qdc.app_id\": appId,\n \"qdc.sdk.version\": SDK_VERSION,\n }\n const mod = qdcModule()\n if (mod) attrs[\"qdc.module\"] = mod\n return attrs\n}\n\nexport function buildResource(): Resource {\n return resourceFromAttributes(buildResourceAttributes())\n}\n","{\n \"name\": \"@quatronic/sdk\",\n \"version\": \"0.3.0\",\n \"type\": \"module\",\n \"private\": false,\n \"publishConfig\": {\n \"registry\": \"https://registry.npmjs.org\",\n \"access\": \"public\"\n },\n \"files\": [\n \"dist\",\n \"semgrep\"\n ],\n \"bin\": {\n \"qdc-setup-env\": \"./dist/cli/setup-env.js\"\n },\n \"exports\": {\n \"./auth\": {\n \"types\": \"./dist/auth/index.d.ts\",\n \"import\": \"./dist/auth/index.js\"\n },\n \"./next/auth\": {\n \"types\": \"./dist/next/auth/index.d.ts\",\n \"import\": \"./dist/next/auth/index.js\"\n },\n \"./next/better-auth\": {\n \"types\": \"./dist/next/better-auth/index.d.ts\",\n \"import\": \"./dist/next/better-auth/index.js\"\n },\n \"./observability\": {\n \"types\": \"./dist/observability/index.d.ts\",\n \"import\": \"./dist/observability/index.js\"\n },\n \"./next/observability\": {\n \"types\": \"./dist/next/observability/index.d.ts\",\n \"import\": \"./dist/next/observability/index.js\"\n },\n \"./next/observability/register\": {\n \"types\": \"./dist/next/observability/register.d.ts\",\n \"import\": \"./dist/next/observability/register.js\"\n },\n \"./node/observability\": {\n \"types\": \"./dist/node/observability/index.d.ts\",\n \"import\": \"./dist/node/observability/index.js\"\n },\n \"./node/observability/register\": {\n \"types\": \"./dist/node/observability/register.d.ts\",\n \"import\": \"./dist/node/observability/register.js\"\n },\n \"./next/config\": {\n \"types\": \"./dist/next/config/index.d.ts\",\n \"import\": \"./dist/next/config/index.js\"\n },\n \"./next/security\": {\n \"types\": \"./dist/next/security/index.d.ts\",\n \"import\": \"./dist/next/security/index.js\"\n },\n \"./next/security/testing\": {\n \"types\": \"./dist/next/security/testing.d.ts\",\n \"import\": \"./dist/next/security/testing.js\"\n },\n \"./eslint\": {\n \"types\": \"./dist/eslint/index.d.ts\",\n \"import\": \"./dist/eslint/index.js\"\n },\n \"./next/connections\": {\n \"types\": \"./dist/next/connections/index.d.ts\",\n \"import\": \"./dist/next/connections/index.js\"\n },\n \"./node/connections\": {\n \"types\": \"./dist/node/connections/index.d.ts\",\n \"import\": \"./dist/node/connections/index.js\"\n },\n \"./node/net\": {\n \"types\": \"./dist/node/net/index.d.ts\",\n \"import\": \"./dist/node/net/index.js\"\n },\n \"./node/fspath\": {\n \"types\": \"./dist/node/fspath/index.d.ts\",\n \"import\": \"./dist/node/fspath/index.js\"\n },\n \"./node/parse\": {\n \"types\": \"./dist/node/parse/index.d.ts\",\n \"import\": \"./dist/node/parse/index.js\"\n },\n \"./node/identity\": {\n \"types\": \"./dist/node/identity/index.d.ts\",\n \"import\": \"./dist/node/identity/index.js\"\n },\n \"./node/db\": {\n \"types\": \"./dist/node/db/index.d.ts\",\n \"import\": \"./dist/node/db/index.js\"\n },\n \"./next/db\": {\n \"types\": \"./dist/next/db/index.d.ts\",\n \"import\": \"./dist/next/db/index.js\"\n }\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"surface\": \"node scripts/api-surface.mjs\",\n \"surface:check\": \"node scripts/api-surface.mjs --check\",\n \"prepublishOnly\": \"pnpm build\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"typecheck\": \"tsc --noEmit && tsc -p tsconfig.test.json\",\n \"lint\": \"eslint src tests\",\n \"calibrate\": \"node scripts/calibrate.mjs\"\n },\n \"dependencies\": {\n \"@opentelemetry/api\": \"^1.9.1\",\n \"@opentelemetry/context-zone\": \"2.7.1\",\n \"@opentelemetry/exporter-logs-otlp-http\": \"^0.218.0\",\n \"@opentelemetry/exporter-metrics-otlp-http\": \"^0.218.0\",\n \"@opentelemetry/exporter-trace-otlp-http\": \"^0.218.0\",\n \"@opentelemetry/instrumentation\": \"^0.218.0\",\n \"@opentelemetry/instrumentation-document-load\": \"^0.63.0\",\n \"@opentelemetry/instrumentation-fetch\": \"^0.218.0\",\n \"@opentelemetry/instrumentation-http\": \"^0.218.0\",\n \"@opentelemetry/instrumentation-pg\": \"^0.71.0\",\n \"@opentelemetry/instrumentation-pino\": \"^0.64.0\",\n \"@opentelemetry/instrumentation-undici\": \"^0.28.0\",\n \"@opentelemetry/resources\": \"^2.7.1\",\n \"@opentelemetry/sdk-logs\": \"^0.218.0\",\n \"@opentelemetry/sdk-metrics\": \"^2.7.1\",\n \"@opentelemetry/sdk-node\": \"^0.218.0\",\n \"@opentelemetry/sdk-trace-base\": \"2.7.1\",\n \"@opentelemetry/sdk-trace-web\": \"2.7.1\",\n \"jose\": \"^5.9.6\",\n \"pino\": \"^10.3.1\"\n },\n \"peerDependencies\": {\n \"@better-auth/core\": \">=1.6\",\n \"better-auth\": \">=1.6\",\n \"drizzle-orm\": \">=0.36\",\n \"eslint\": \">=9\",\n \"next\": \">=15\",\n \"pg\": \">=8.13\",\n \"react\": \">=18\",\n \"react-dom\": \">=18\"\n },\n \"peerDependenciesMeta\": {\n \"eslint\": {\n \"optional\": true\n },\n \"react\": {\n \"optional\": true\n },\n \"react-dom\": {\n \"optional\": true\n },\n \"next\": {\n \"optional\": true\n },\n \"drizzle-orm\": {\n \"optional\": true\n },\n \"pg\": {\n \"optional\": true\n },\n \"better-auth\": {\n \"optional\": true\n },\n \"@better-auth/core\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@better-auth/core\": \"^1.6.24\",\n \"@eslint/js\": \"^10.0.1\",\n \"@opentelemetry/instrumentation\": \"^0.218.0\",\n \"@opentelemetry/sdk-trace-base\": \"^2.7.0\",\n \"@testcontainers/postgresql\": \"^12.0.0\",\n \"@testing-library/react\": \"^16.1.0\",\n \"@types/node\": \"^22.10.2\",\n \"@types/pg\": \"^8.11.10\",\n \"@types/react\": \"^18.3.17\",\n \"@types/react-dom\": \"^18.3.5\",\n \"@vitest/coverage-v8\": \"^2.1.9\",\n \"better-auth\": \"^1.6.24\",\n \"drizzle-kit\": \"^0.30.1\",\n \"drizzle-orm\": \"^0.38.2\",\n \"eslint\": \"^10.5.0\",\n \"jsdom\": \"^25.0.1\",\n \"msw\": \"^2.7.0\",\n \"next\": \"^15.1.0\",\n \"pg\": \"^8.13.1\",\n \"react\": \"^18.3.1\",\n \"react-dom\": \"^18.3.1\",\n \"testcontainers\": \"^10.16.0\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.7.2\",\n \"typescript-eslint\": \"^8.61.1\",\n \"vitest\": \"^2.1.8\"\n }\n}\n","// Pure predicate deciding whether an HTTP request is infrastructural noise that\n// should never become a span. Framework-agnostic rules are built in: favicon,\n// source maps, OPTIONS, RSC navigations/prefetches (`?_rsc=` query + RSC headers),\n// and Next's `/_next/*` internals. Callers pass any additional environment-specific\n// prefixes (and an optional health path) via NoiseFilterOptions.\n\nexport interface NoiseFilterOptions {\n healthPath?: string\n noisePrefixes?: string[]\n}\n\n// `/api/auth/me` is the SDK's own session poll (PortalProvider fires it on every\n// page mount) — a heartbeat, not user activity. The meaningful auth flows keep\n// their labeled spans (Log in, Complete login, Log out, Refresh session);\n// dropping the inbound span here also drops its pg children (requireParentSpan).\nconst NOISE_EXACT = new Set([\"/favicon.ico\", \"/api/auth/me\"])\n\n// React Server Components navigations/prefetches/data-fetches. Next signals them\n// with a `?_rsc=` query param and/or an `RSC` / `Next-Router-Prefetch` request\n// header. They are real-looking routes, so a path-prefix filter misses them.\n// NOTE: `Next-Router-State-Tree` is intentionally NOT in this list — Next.js\n// sends it on server actions too (POST + Next-Action), not only on RSC navigations,\n// so it is not a safe RSC discriminator.\nconst RSC_QUERY_RE = /[?&]_rsc=/\nconst RSC_HEADERS = [\"rsc\", \"next-router-prefetch\"]\n\nexport function isNoisePath(rawUrl: string, opts: NoiseFilterOptions = {}): boolean {\n if (RSC_QUERY_RE.test(rawUrl)) return true\n const path = (rawUrl.split(\"?\")[0] ?? \"\").trim()\n if (!path) return false\n if (NOISE_EXACT.has(path)) return true\n if (path.endsWith(\".map\")) return true\n if (path.startsWith(\"/_next/\")) return true\n if ((opts.noisePrefixes ?? []).some((p) => path.startsWith(p))) return true\n if (opts.healthPath && path === opts.healthPath) return true\n return false\n}\n\nexport function shouldIgnoreIncoming(\n req: { url?: string; method?: string; headers?: Record<string, unknown> },\n opts: NoiseFilterOptions = {},\n): boolean {\n if ((req.method ?? \"\").toUpperCase() === \"OPTIONS\") return true\n const headers = req.headers ?? {}\n // A Next.js server action is real work — never noise — even though it also\n // carries router headers. Exempt it explicitly so its inbound span (and the\n // DB child gated by pg requireParentSpan) is preserved.\n if (headers[\"next-action\"] != null) return false\n if (RSC_HEADERS.some((h) => headers[h] != null)) return true\n return isNoisePath(req.url ?? \"\", opts)\n}\n\nexport function shouldIgnoreOutgoing(\n req: { path?: string },\n opts: NoiseFilterOptions = {},\n): boolean {\n return isNoisePath(req.path ?? \"\", opts)\n}\n","// Pure HTTP-span PII sanitizer. No OTel SDK import so it is unit-testable in\n// isolation. register.ts wires sanitizeHttpSpanAttributes into the\n// HttpInstrumentation requestHook when QDC_OTEL_SANITIZE_HTTP is on.\n\nconst REDACTED = \"[redacted]\"\n\nexport type SemconvMode = \"legacy\" | \"stable\" | \"dup\"\n\n// instrumentation-http emits legacy attribute names by default and the stable\n// names (url.full/url.query/url.path) only when OTEL_SEMCONV_STABILITY_OPT_IN\n// selects \"http\" (stable only) or \"http/dup\" (both).\nexport function httpSemconvMode(\n optIn: string | undefined = process.env.OTEL_SEMCONV_STABILITY_OPT_IN,\n): SemconvMode {\n const tokens = (optIn ?? \"\").split(\",\").map((t) => t.trim().toLowerCase())\n if (tokens.includes(\"http/dup\")) return \"dup\"\n if (tokens.includes(\"http\")) return \"stable\"\n return \"legacy\"\n}\n\ninterface SpanLike {\n setAttribute(key: string, value: string): unknown\n}\n\ninterface RequestLike {\n url?: string // IncomingMessage (server spans): path + query\n path?: string // ClientRequest (outgoing spans): path + query\n}\n\nexport function sanitizeHttpSpanAttributes(\n span: SpanLike,\n request: RequestLike,\n mode: SemconvMode = httpSemconvMode(),\n): void {\n const raw = request.url ?? request.path ?? \"\"\n const queryStart = raw.indexOf(\"?\")\n const hasQuery = queryStart !== -1\n const path = hasQuery ? raw.slice(0, queryStart) : raw\n\n // Legacy semconv: redact http.url (once the query is gone it only duplicates\n // http.host + http.target); http.target keeps the path. Skip http.target when\n // we have no path info, so we don't clobber the instrumentation's \"/\" default.\n if (mode === \"legacy\" || mode === \"dup\") {\n if (path) span.setAttribute(\"http.target\", path)\n span.setAttribute(\"http.url\", REDACTED)\n }\n\n // Stable semconv: the query lives in url.full / url.query; url.path is already\n // query-less, so leave it intact. Only redact url.query when a query was\n // actually present — the instrumentation omits it otherwise, and writing it\n // unconditionally would falsely signal a redacted query on clean paths.\n if (mode === \"stable\" || mode === \"dup\") {\n span.setAttribute(\"url.full\", REDACTED)\n if (hasQuery) span.setAttribute(\"url.query\", REDACTED)\n }\n}\n","// Leaf-noise predicate + attribute redaction, pure so they unit-test without the\n// OTel SDK. Wired into export by scrub-span-processor.ts. Contract:\n// docs (QDC spec 2026-07-02): the SDK drops ONLY leaf spans — spans that never\n// have children — so parent/child chains can never break. Structural framework\n// spans (BaseServer.handleRequest, AppRender.fetch, undici) stay; the portal\n// folds those at render time.\n\nexport const REDACTED = \"●●●\"\n\n// next.span_type values that are pure leaves and never carry information a\n// developer needs: sub-millisecond router/renderer bookkeeping.\nconst NEXT_LEAF_NOISE = new Set([\n \"Middleware.execute\",\n \"NextNodeServer.findPageComponents\",\n \"NextNodeServer.startResponse\",\n])\n\n// pg connection-pool bookkeeping; the actual query span (pg.query:*) stays.\nconst NOISE_SPAN_NAMES = new Set([\"pg-pool.connect\", \"pg.connect\"])\n\nexport function isNoiseLeafSpan(name: string, attributes: Record<string, unknown>): boolean {\n const nextType = attributes[\"next.span_type\"]\n if (typeof nextType === \"string\" && NEXT_LEAF_NOISE.has(nextType)) return true\n return NOISE_SPAN_NAMES.has(name)\n}\n\nconst REDACT_KEYS = new Set([\"db.connection_string\", \"db.user\"])\nconst REDACT_PREFIXES = [\"net.peer.\", \"net.sock.\", \"net.host.\", \"network.peer.\", \"network.local.\"]\n\nexport function redactSpanAttributes(attributes: Record<string, unknown>): void {\n for (const key of Object.keys(attributes)) {\n if (REDACT_KEYS.has(key) || REDACT_PREFIXES.some((p) => key.startsWith(p))) {\n attributes[key] = REDACTED\n }\n }\n}\n","import type { Context } from \"@opentelemetry/api\"\nimport type { ReadableSpan, Span, SpanProcessor } from \"@opentelemetry/sdk-trace-base\"\nimport { isNoiseLeafSpan, redactSpanAttributes } from \"./span-scrub\"\n\n/** Wraps the export processor: drops leaf-noise spans and redacts sensitive\n * attributes on everything else. Runs in ALL envs — connection strings and\n * internal IPs never belong in the telemetry backend. */\nexport class ScrubSpanProcessor implements SpanProcessor {\n constructor(private readonly inner: SpanProcessor) {}\n\n onStart(span: Span, parentContext: Context): void {\n this.inner.onStart(span, parentContext)\n }\n\n onEnd(span: ReadableSpan): void {\n if (isNoiseLeafSpan(span.name, span.attributes as Record<string, unknown>)) return\n redactSpanAttributes(span.attributes as Record<string, unknown>)\n this.inner.onEnd(span)\n }\n\n forceFlush(): Promise<void> {\n return this.inner.forceFlush()\n }\n\n shutdown(): Promise<void> {\n return this.inner.shutdown()\n }\n}\n","// A crash that reaches the SDK's last-resort handlers is often the only thing an\n// operator ever sees about it: the process dies before any log exporter flushes,\n// so all that survives is this one stderr line in the platform's container log.\n// `${err}` would reduce it to \"Error: self-signed certificate\" — no stack, no\n// cause, no error code, i.e. no way to tell which of the app's boot steps threw.\nexport function formatFatal(err: unknown): string {\n if (!(err instanceof Error)) return String(err)\n\n let out = err.stack ?? `${err.name}: ${err.message}`\n\n const code = (err as { code?: unknown }).code\n if (typeof code === \"string\" || typeof code === \"number\") out += `\\n code: ${code}`\n\n // Fetch/undici and pg wrap the real failure in `cause`; without it a boot\n // crash reads as a generic \"TypeError: fetch failed\".\n let cause: unknown = (err as { cause?: unknown }).cause\n let depth = 0\n while (cause !== undefined && depth < 3) {\n const rendered = cause instanceof Error ? (cause.stack ?? `${cause.name}: ${cause.message}`) : String(cause)\n out += `\\n caused by: ${rendered}`\n cause = cause instanceof Error ? (cause as { cause?: unknown }).cause : undefined\n depth += 1\n }\n\n return out\n}\n"],"mappings":"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","names":["REDACTED"]}
|
|
1
|
+
{"version":3,"sources":["../src/observability-core/start-node-sdk.ts","../src/observability-core/resource.ts","../package.json","../src/observability-core/noise-filter.ts","../src/observability-core/http-sanitize.ts","../src/observability-core/span-scrub.ts","../src/observability-core/scrub-span-processor.ts","../src/observability-core/format-fatal.ts"],"sourcesContent":["// Shared NodeSDK bootstrap for every server runtime (Next and plain Node). The\n// only per-runtime difference is the noise-prefix list. Importing this module's\n// caller (a register entry) must happen before pino/node:http are first imported\n// so the instrumentations can patch them.\nimport { NodeSDK } from \"@opentelemetry/sdk-node\"\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-http\"\nimport { OTLPMetricExporter } from \"@opentelemetry/exporter-metrics-otlp-http\"\nimport { OTLPLogExporter } from \"@opentelemetry/exporter-logs-otlp-http\"\nimport { PeriodicExportingMetricReader } from \"@opentelemetry/sdk-metrics\"\nimport { BatchLogRecordProcessor } from \"@opentelemetry/sdk-logs\"\nimport { BatchSpanProcessor } from \"@opentelemetry/sdk-trace-base\"\nimport { HttpInstrumentation } from \"@opentelemetry/instrumentation-http\"\nimport { UndiciInstrumentation } from \"@opentelemetry/instrumentation-undici\"\nimport { PinoInstrumentation } from \"@opentelemetry/instrumentation-pino\"\nimport { PgInstrumentation } from \"@opentelemetry/instrumentation-pg\"\nimport { buildResource } from \"./resource\"\nimport { qdcSanitizeHttp, qdcTracesSampleRatio, qdcEnhancedDbReporting, qdcHealthPath } from \"./env\"\nimport { shouldIgnoreIncoming, shouldIgnoreOutgoing } from \"./noise-filter\"\nimport { sanitizeHttpSpanAttributes } from \"./http-sanitize\"\nimport { ScrubSpanProcessor } from \"./scrub-span-processor\"\nimport { formatFatal } from \"./format-fatal\"\n\nexport interface StartNodeSdkOptions {\n noisePrefixes: string[]\n}\n\nexport function startNodeSdk(opts: StartNodeSdkOptions): NodeSDK {\n const { noisePrefixes } = opts\n\n // Sampling defaults before NodeSDK reads env. Default 100% in all envs; an\n // explicit OTEL_TRACES_SAMPLER always wins.\n if (!process.env.OTEL_TRACES_SAMPLER) process.env.OTEL_TRACES_SAMPLER = \"parentbased_traceidratio\"\n if (!process.env.OTEL_TRACES_SAMPLER_ARG) process.env.OTEL_TRACES_SAMPLER_ARG = qdcTracesSampleRatio()\n\n const healthPath = qdcHealthPath()\n\n const httpInstrumentation = new HttpInstrumentation({\n ignoreIncomingRequestHook: (req) => shouldIgnoreIncoming(req, { healthPath, noisePrefixes }),\n ignoreOutgoingRequestHook: (req) => shouldIgnoreOutgoing({ path: req.path ?? undefined }, { healthPath, noisePrefixes }),\n ...(qdcSanitizeHttp()\n ? { requestHook: (span, request) => sanitizeHttpSpanAttributes(span, request as { url?: string; path?: string }) }\n : {}),\n })\n\n // Cross-module / cross-service propagation: global fetch (undici) is the natural\n // way a Next server and a Node backend call CONN_<ALIAS>_URL. instrumentation-http\n // does NOT see undici, so without this the traceparent is never injected and the\n // hop starts a new trace. Injection is unconditional on origin (server-to-server,\n // no CORS) — that is what continues the trace across modules.\n const undiciInstrumentation = new UndiciInstrumentation({\n ignoreRequestHook: (request) =>\n shouldIgnoreOutgoing({ path: (request as { path?: string }).path }, { healthPath, noisePrefixes }),\n ...(qdcSanitizeHttp()\n ? { requestHook: (span, request) =>\n sanitizeHttpSpanAttributes(span, { path: (request as { path?: string }).path }, \"stable\") }\n : {}),\n })\n\n // DB spans. Full SQL + values only off-prod (synthetic data); parametrized only\n // in prod-like envs. `requireParentSpan` drops queries that run with no active\n // parent span — connection-pool warmup, keepalive pings, startup/migration — so\n // each no longer surfaces as its own root trace. Queries inside an HTTP request\n // (or an `observe()` wrapper) still nest under that span and are kept.\n const pgInstrumentation = new PgInstrumentation({\n enhancedDatabaseReporting: qdcEnhancedDbReporting(),\n requireParentSpan: true,\n })\n\n let sdk: NodeSDK\n try {\n sdk = new NodeSDK({\n resource: buildResource(),\n spanProcessors: [new ScrubSpanProcessor(new BatchSpanProcessor(new OTLPTraceExporter()))],\n metricReader: new PeriodicExportingMetricReader({ exporter: new OTLPMetricExporter() }),\n logRecordProcessor: new BatchLogRecordProcessor(new OTLPLogExporter()),\n instrumentations: [httpInstrumentation, undiciInstrumentation, pgInstrumentation, new PinoInstrumentation()],\n })\n } catch (err: unknown) {\n process.stderr.write(`[qdc-sdk] initialization failed: ${err}\\n`)\n process.exit(1)\n }\n\n try {\n sdk.start()\n } catch (err: unknown) {\n process.stderr.write(`[qdc-sdk] SDK start failed: ${err}\\n`)\n process.exit(1)\n }\n\n const gracefulShutdown = async (signal: string): Promise<void> => {\n process.stderr.write(`[qdc-sdk] ${signal} received, shutting down\\n`)\n try { await sdk.shutdown() } catch { /* ignore */ }\n process.exit(0)\n }\n process.on(\"SIGTERM\", () => void gracefulShutdown(\"SIGTERM\"))\n process.on(\"SIGINT\", () => void gracefulShutdown(\"SIGINT\"))\n process.on(\"uncaughtException\", async (err) => {\n process.stderr.write(`[qdc-sdk] fatal: ${formatFatal(err)}\\n`)\n try { await sdk.shutdown() } finally { process.exit(1) }\n })\n process.on(\"unhandledRejection\", async (reason) => {\n process.stderr.write(`[qdc-sdk] fatal: ${formatFatal(reason)}\\n`)\n try { await sdk.shutdown() } finally { process.exit(1) }\n })\n\n return sdk\n}\n","import { type Resource, resourceFromAttributes } from \"@opentelemetry/resources\"\nimport { hostname } from \"node:os\"\nimport { qdcAppId, qdcCustomerId, qdcEnv, qdcModule } from \"./env\"\nimport pkg from \"../../package.json\" with { type: \"json\" }\n\nconst SDK_VERSION = (pkg as { version: string }).version\n\n/**\n * Maps the QDC identity env vars to the OpenTelemetry resource attributes used\n * by the SDK's server-side observability. The NodeSDK carries this resource on\n * every span and log record (the latter via the in-process PinoInstrumentation),\n * so it is the single source of truth for tenant labels.\n *\n * Identity is read from NEXT_PUBLIC_QDC_* with a fallback to legacy QDC_* (see\n * ./env). Throws if the customer or app id are missing — required to land logs\n * and traces under the correct tenant namespace.\n */\nexport function buildResourceAttributes(): Record<string, string> {\n const customerId = qdcCustomerId()\n if (!customerId)\n throw new Error(\"NEXT_PUBLIC_QDC_CUSTOMER_ID (or legacy QDC_CUSTOMER_ID) env var is required\")\n\n const appId = qdcAppId()\n if (!appId)\n throw new Error(\"NEXT_PUBLIC_QDC_APP_ID (or legacy QDC_APP_ID) env var is required\")\n\n const env = qdcEnv()\n\n const attrs: Record<string, string> = {\n \"service.name\": appId,\n \"service.namespace\": customerId,\n \"deployment.environment\": env,\n \"host.name\": hostname(),\n \"qdc.customer_id\": customerId,\n \"qdc.app_id\": appId,\n \"qdc.sdk.version\": SDK_VERSION,\n }\n const mod = qdcModule()\n if (mod) attrs[\"qdc.module\"] = mod\n return attrs\n}\n\nexport function buildResource(): Resource {\n return resourceFromAttributes(buildResourceAttributes())\n}\n","{\n \"name\": \"@quatronic/sdk\",\n \"version\": \"0.3.1\",\n \"type\": \"module\",\n \"private\": false,\n \"publishConfig\": {\n \"registry\": \"https://registry.npmjs.org\",\n \"access\": \"public\"\n },\n \"files\": [\n \"dist\",\n \"semgrep\"\n ],\n \"bin\": {\n \"qdc-setup-env\": \"./dist/cli/setup-env.js\"\n },\n \"exports\": {\n \"./auth\": {\n \"types\": \"./dist/auth/index.d.ts\",\n \"import\": \"./dist/auth/index.js\"\n },\n \"./next/auth\": {\n \"types\": \"./dist/next/auth/index.d.ts\",\n \"import\": \"./dist/next/auth/index.js\"\n },\n \"./next/better-auth\": {\n \"types\": \"./dist/next/better-auth/index.d.ts\",\n \"import\": \"./dist/next/better-auth/index.js\"\n },\n \"./observability\": {\n \"types\": \"./dist/observability/index.d.ts\",\n \"import\": \"./dist/observability/index.js\"\n },\n \"./next/observability\": {\n \"types\": \"./dist/next/observability/index.d.ts\",\n \"import\": \"./dist/next/observability/index.js\"\n },\n \"./next/observability/register\": {\n \"types\": \"./dist/next/observability/register.d.ts\",\n \"import\": \"./dist/next/observability/register.js\"\n },\n \"./node/observability\": {\n \"types\": \"./dist/node/observability/index.d.ts\",\n \"import\": \"./dist/node/observability/index.js\"\n },\n \"./node/observability/register\": {\n \"types\": \"./dist/node/observability/register.d.ts\",\n \"import\": \"./dist/node/observability/register.js\"\n },\n \"./next/config\": {\n \"types\": \"./dist/next/config/index.d.ts\",\n \"import\": \"./dist/next/config/index.js\"\n },\n \"./next/security\": {\n \"types\": \"./dist/next/security/index.d.ts\",\n \"import\": \"./dist/next/security/index.js\"\n },\n \"./next/security/testing\": {\n \"types\": \"./dist/next/security/testing.d.ts\",\n \"import\": \"./dist/next/security/testing.js\"\n },\n \"./eslint\": {\n \"types\": \"./dist/eslint/index.d.ts\",\n \"import\": \"./dist/eslint/index.js\"\n },\n \"./next/connections\": {\n \"types\": \"./dist/next/connections/index.d.ts\",\n \"import\": \"./dist/next/connections/index.js\"\n },\n \"./node/connections\": {\n \"types\": \"./dist/node/connections/index.d.ts\",\n \"import\": \"./dist/node/connections/index.js\"\n },\n \"./node/net\": {\n \"types\": \"./dist/node/net/index.d.ts\",\n \"import\": \"./dist/node/net/index.js\"\n },\n \"./node/fspath\": {\n \"types\": \"./dist/node/fspath/index.d.ts\",\n \"import\": \"./dist/node/fspath/index.js\"\n },\n \"./node/parse\": {\n \"types\": \"./dist/node/parse/index.d.ts\",\n \"import\": \"./dist/node/parse/index.js\"\n },\n \"./node/identity\": {\n \"types\": \"./dist/node/identity/index.d.ts\",\n \"import\": \"./dist/node/identity/index.js\"\n },\n \"./node/db\": {\n \"types\": \"./dist/node/db/index.d.ts\",\n \"import\": \"./dist/node/db/index.js\"\n },\n \"./next/db\": {\n \"types\": \"./dist/next/db/index.d.ts\",\n \"import\": \"./dist/next/db/index.js\"\n }\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"surface\": \"node scripts/api-surface.mjs\",\n \"surface:check\": \"node scripts/api-surface.mjs --check\",\n \"prepublishOnly\": \"pnpm build\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"typecheck\": \"tsc --noEmit && tsc -p tsconfig.test.json\",\n \"lint\": \"eslint src tests\",\n \"calibrate\": \"node scripts/calibrate.mjs\"\n },\n \"dependencies\": {\n \"@opentelemetry/api\": \"^1.9.1\",\n \"@opentelemetry/context-zone\": \"2.7.1\",\n \"@opentelemetry/exporter-logs-otlp-http\": \"^0.218.0\",\n \"@opentelemetry/exporter-metrics-otlp-http\": \"^0.218.0\",\n \"@opentelemetry/exporter-trace-otlp-http\": \"^0.218.0\",\n \"@opentelemetry/instrumentation\": \"^0.218.0\",\n \"@opentelemetry/instrumentation-document-load\": \"^0.63.0\",\n \"@opentelemetry/instrumentation-fetch\": \"^0.218.0\",\n \"@opentelemetry/instrumentation-http\": \"^0.218.0\",\n \"@opentelemetry/instrumentation-pg\": \"^0.71.0\",\n \"@opentelemetry/instrumentation-pino\": \"^0.64.0\",\n \"@opentelemetry/instrumentation-undici\": \"^0.28.0\",\n \"@opentelemetry/resources\": \"^2.7.1\",\n \"@opentelemetry/sdk-logs\": \"^0.218.0\",\n \"@opentelemetry/sdk-metrics\": \"^2.7.1\",\n \"@opentelemetry/sdk-node\": \"^0.218.0\",\n \"@opentelemetry/sdk-trace-base\": \"2.7.1\",\n \"@opentelemetry/sdk-trace-web\": \"2.7.1\",\n \"jose\": \"^5.9.6\",\n \"pino\": \"^10.3.1\"\n },\n \"peerDependencies\": {\n \"@better-auth/core\": \">=1.6\",\n \"better-auth\": \">=1.6\",\n \"drizzle-orm\": \">=0.36\",\n \"eslint\": \">=9\",\n \"next\": \">=15\",\n \"pg\": \">=8.13\",\n \"react\": \">=18\",\n \"react-dom\": \">=18\"\n },\n \"peerDependenciesMeta\": {\n \"eslint\": {\n \"optional\": true\n },\n \"react\": {\n \"optional\": true\n },\n \"react-dom\": {\n \"optional\": true\n },\n \"next\": {\n \"optional\": true\n },\n \"drizzle-orm\": {\n \"optional\": true\n },\n \"pg\": {\n \"optional\": true\n },\n \"better-auth\": {\n \"optional\": true\n },\n \"@better-auth/core\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@better-auth/core\": \"^1.6.24\",\n \"@eslint/js\": \"^10.0.1\",\n \"@opentelemetry/instrumentation\": \"^0.218.0\",\n \"@opentelemetry/sdk-trace-base\": \"^2.7.0\",\n \"@testcontainers/postgresql\": \"^12.0.0\",\n \"@testing-library/react\": \"^16.1.0\",\n \"@types/node\": \"^22.10.2\",\n \"@types/pg\": \"^8.11.10\",\n \"@types/react\": \"^18.3.17\",\n \"@types/react-dom\": \"^18.3.5\",\n \"@vitest/coverage-v8\": \"^2.1.9\",\n \"better-auth\": \"^1.6.24\",\n \"drizzle-kit\": \"^0.30.1\",\n \"drizzle-orm\": \"^0.38.2\",\n \"eslint\": \"^10.5.0\",\n \"jsdom\": \"^25.0.1\",\n \"msw\": \"^2.7.0\",\n \"next\": \"^15.1.0\",\n \"pg\": \"^8.13.1\",\n \"react\": \"^18.3.1\",\n \"react-dom\": \"^18.3.1\",\n \"testcontainers\": \"^10.16.0\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.7.2\",\n \"typescript-eslint\": \"^8.61.1\",\n \"vitest\": \"^2.1.8\"\n }\n}\n","// Pure predicate deciding whether an HTTP request is infrastructural noise that\n// should never become a span. Framework-agnostic rules are built in: favicon,\n// source maps, OPTIONS, RSC navigations/prefetches (`?_rsc=` query + RSC headers),\n// and Next's `/_next/*` internals. Callers pass any additional environment-specific\n// prefixes (and an optional health path) via NoiseFilterOptions.\n\nexport interface NoiseFilterOptions {\n healthPath?: string\n noisePrefixes?: string[]\n}\n\n// `/api/auth/me` is the SDK's own session poll (PortalProvider fires it on every\n// page mount) — a heartbeat, not user activity. The meaningful auth flows keep\n// their labeled spans (Log in, Complete login, Log out, Refresh session);\n// dropping the inbound span here also drops its pg children (requireParentSpan).\nconst NOISE_EXACT = new Set([\"/favicon.ico\", \"/api/auth/me\"])\n\n// React Server Components navigations/prefetches/data-fetches. Next signals them\n// with a `?_rsc=` query param and/or an `RSC` / `Next-Router-Prefetch` request\n// header. They are real-looking routes, so a path-prefix filter misses them.\n// NOTE: `Next-Router-State-Tree` is intentionally NOT in this list — Next.js\n// sends it on server actions too (POST + Next-Action), not only on RSC navigations,\n// so it is not a safe RSC discriminator.\nconst RSC_QUERY_RE = /[?&]_rsc=/\nconst RSC_HEADERS = [\"rsc\", \"next-router-prefetch\"]\n\nexport function isNoisePath(rawUrl: string, opts: NoiseFilterOptions = {}): boolean {\n if (RSC_QUERY_RE.test(rawUrl)) return true\n const path = (rawUrl.split(\"?\")[0] ?? \"\").trim()\n if (!path) return false\n if (NOISE_EXACT.has(path)) return true\n if (path.endsWith(\".map\")) return true\n if (path.startsWith(\"/_next/\")) return true\n if ((opts.noisePrefixes ?? []).some((p) => path.startsWith(p))) return true\n if (opts.healthPath && path === opts.healthPath) return true\n return false\n}\n\nexport function shouldIgnoreIncoming(\n req: { url?: string; method?: string; headers?: Record<string, unknown> },\n opts: NoiseFilterOptions = {},\n): boolean {\n if ((req.method ?? \"\").toUpperCase() === \"OPTIONS\") return true\n const headers = req.headers ?? {}\n // A Next.js server action is real work — never noise — even though it also\n // carries router headers. Exempt it explicitly so its inbound span (and the\n // DB child gated by pg requireParentSpan) is preserved.\n if (headers[\"next-action\"] != null) return false\n if (RSC_HEADERS.some((h) => headers[h] != null)) return true\n return isNoisePath(req.url ?? \"\", opts)\n}\n\nexport function shouldIgnoreOutgoing(\n req: { path?: string },\n opts: NoiseFilterOptions = {},\n): boolean {\n return isNoisePath(req.path ?? \"\", opts)\n}\n","// Pure HTTP-span PII sanitizer. No OTel SDK import so it is unit-testable in\n// isolation. register.ts wires sanitizeHttpSpanAttributes into the\n// HttpInstrumentation requestHook when QDC_OTEL_SANITIZE_HTTP is on.\n\nconst REDACTED = \"[redacted]\"\n\nexport type SemconvMode = \"legacy\" | \"stable\" | \"dup\"\n\n// instrumentation-http emits legacy attribute names by default and the stable\n// names (url.full/url.query/url.path) only when OTEL_SEMCONV_STABILITY_OPT_IN\n// selects \"http\" (stable only) or \"http/dup\" (both).\nexport function httpSemconvMode(\n optIn: string | undefined = process.env.OTEL_SEMCONV_STABILITY_OPT_IN,\n): SemconvMode {\n const tokens = (optIn ?? \"\").split(\",\").map((t) => t.trim().toLowerCase())\n if (tokens.includes(\"http/dup\")) return \"dup\"\n if (tokens.includes(\"http\")) return \"stable\"\n return \"legacy\"\n}\n\ninterface SpanLike {\n setAttribute(key: string, value: string): unknown\n}\n\ninterface RequestLike {\n url?: string // IncomingMessage (server spans): path + query\n path?: string // ClientRequest (outgoing spans): path + query\n}\n\nexport function sanitizeHttpSpanAttributes(\n span: SpanLike,\n request: RequestLike,\n mode: SemconvMode = httpSemconvMode(),\n): void {\n const raw = request.url ?? request.path ?? \"\"\n const queryStart = raw.indexOf(\"?\")\n const hasQuery = queryStart !== -1\n const path = hasQuery ? raw.slice(0, queryStart) : raw\n\n // Legacy semconv: redact http.url (once the query is gone it only duplicates\n // http.host + http.target); http.target keeps the path. Skip http.target when\n // we have no path info, so we don't clobber the instrumentation's \"/\" default.\n if (mode === \"legacy\" || mode === \"dup\") {\n if (path) span.setAttribute(\"http.target\", path)\n span.setAttribute(\"http.url\", REDACTED)\n }\n\n // Stable semconv: the query lives in url.full / url.query; url.path is already\n // query-less, so leave it intact. Only redact url.query when a query was\n // actually present — the instrumentation omits it otherwise, and writing it\n // unconditionally would falsely signal a redacted query on clean paths.\n if (mode === \"stable\" || mode === \"dup\") {\n span.setAttribute(\"url.full\", REDACTED)\n if (hasQuery) span.setAttribute(\"url.query\", REDACTED)\n }\n}\n","// Leaf-noise predicate + attribute redaction, pure so they unit-test without the\n// OTel SDK. Wired into export by scrub-span-processor.ts. Contract:\n// docs (QDC spec 2026-07-02): the SDK drops ONLY leaf spans — spans that never\n// have children — so parent/child chains can never break. Structural framework\n// spans (BaseServer.handleRequest, AppRender.fetch, undici) stay; the portal\n// folds those at render time.\n\nexport const REDACTED = \"●●●\"\n\n// next.span_type values that are pure leaves and never carry information a\n// developer needs: sub-millisecond router/renderer bookkeeping.\nconst NEXT_LEAF_NOISE = new Set([\n \"Middleware.execute\",\n \"NextNodeServer.findPageComponents\",\n \"NextNodeServer.startResponse\",\n])\n\n// pg connection-pool bookkeeping; the actual query span (pg.query:*) stays.\nconst NOISE_SPAN_NAMES = new Set([\"pg-pool.connect\", \"pg.connect\"])\n\nexport function isNoiseLeafSpan(name: string, attributes: Record<string, unknown>): boolean {\n const nextType = attributes[\"next.span_type\"]\n if (typeof nextType === \"string\" && NEXT_LEAF_NOISE.has(nextType)) return true\n return NOISE_SPAN_NAMES.has(name)\n}\n\nconst REDACT_KEYS = new Set([\"db.connection_string\", \"db.user\"])\nconst REDACT_PREFIXES = [\"net.peer.\", \"net.sock.\", \"net.host.\", \"network.peer.\", \"network.local.\"]\n\nexport function redactSpanAttributes(attributes: Record<string, unknown>): void {\n for (const key of Object.keys(attributes)) {\n if (REDACT_KEYS.has(key) || REDACT_PREFIXES.some((p) => key.startsWith(p))) {\n attributes[key] = REDACTED\n }\n }\n}\n","import type { Context } from \"@opentelemetry/api\"\nimport type { ReadableSpan, Span, SpanProcessor } from \"@opentelemetry/sdk-trace-base\"\nimport { isNoiseLeafSpan, redactSpanAttributes } from \"./span-scrub\"\n\n/** Wraps the export processor: drops leaf-noise spans and redacts sensitive\n * attributes on everything else. Runs in ALL envs — connection strings and\n * internal IPs never belong in the telemetry backend. */\nexport class ScrubSpanProcessor implements SpanProcessor {\n constructor(private readonly inner: SpanProcessor) {}\n\n onStart(span: Span, parentContext: Context): void {\n this.inner.onStart(span, parentContext)\n }\n\n onEnd(span: ReadableSpan): void {\n if (isNoiseLeafSpan(span.name, span.attributes as Record<string, unknown>)) return\n redactSpanAttributes(span.attributes as Record<string, unknown>)\n this.inner.onEnd(span)\n }\n\n forceFlush(): Promise<void> {\n return this.inner.forceFlush()\n }\n\n shutdown(): Promise<void> {\n return this.inner.shutdown()\n }\n}\n","// A crash that reaches the SDK's last-resort handlers is often the only thing an\n// operator ever sees about it: the process dies before any log exporter flushes,\n// so all that survives is this one stderr line in the platform's container log.\n// `${err}` would reduce it to \"Error: self-signed certificate\" — no stack, no\n// cause, no error code, i.e. no way to tell which of the app's boot steps threw.\nexport function formatFatal(err: unknown): string {\n if (!(err instanceof Error)) return String(err)\n\n let out = err.stack ?? `${err.name}: ${err.message}`\n\n const code = (err as { code?: unknown }).code\n if (typeof code === \"string\" || typeof code === \"number\") out += `\\n code: ${code}`\n\n // Fetch/undici and pg wrap the real failure in `cause`; without it a boot\n // crash reads as a generic \"TypeError: fetch failed\".\n let cause: unknown = (err as { cause?: unknown }).cause\n let depth = 0\n while (cause !== undefined && depth < 3) {\n const rendered = cause instanceof Error ? (cause.stack ?? `${cause.name}: ${cause.message}`) : String(cause)\n out += `\\n caused by: ${rendered}`\n cause = cause instanceof Error ? (cause as { cause?: unknown }).cause : undefined\n depth += 1\n }\n\n return out\n}\n"],"mappings":"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","names":["REDACTED"]}
|