feat(core-shared): wire PII scrub processors FIRST in OTel pipeline

This commit is contained in:
2026-05-11 12:09:11 +02:00
parent 6ec5aeb31f
commit ad609f8f01
2 changed files with 13 additions and 9 deletions

View File

@@ -5,6 +5,7 @@ import { UndiciInstrumentation } from "@opentelemetry/instrumentation-undici";
import { PgInstrumentation } from "@opentelemetry/instrumentation-pg";
import { buildResource } from "./resource";
import { createSentryOtelBridge } from "./sentry-bridge";
import { PiiScrubSpanProcessor, PiiScrubLogRecordProcessor } from "./pii-scrub-processor";
const { BatchSpanProcessor } = tracing;
@@ -21,11 +22,11 @@ export type InitOtelServerNodeOpts = {
/**
* Initializes the OpenTelemetry NodeSDK for a server-side app.
* - Configures Resource attributes per OTel semantic conventions.
* - Registers PII scrub processors FIRST so all downstream exporters see clean data.
* - Registers Sentry span processor (via createSentryOtelBridge) when DSN is set.
* - Registers Sentry log record processor when DSN is set.
* - Registers an in-process MeterProvider (no exporter — Sentry metrics not yet
* wired; a future phase or vendor-specific exporter can add a MetricReader).
* - PII scrub processors land in Phase 5.
*
* Caller is responsible for `sdk.shutdown()` on process exit.
*/
@@ -38,14 +39,17 @@ export function initOtelServerNode(opts: InitOtelServerNodeOpts): NodeSDK {
});
const bridge = createSentryOtelBridge({ dsn: opts.dsn });
// PiiScrubSpanProcessor runs FIRST so the Sentry exporter never sees raw PII.
const spanProcessors = bridge.spanProcessor
? [new BatchSpanProcessor(bridge.spanProcessor as never)]
: [];
// Register SentryLogRecordForwarder directly as a processor — it implements
// LogRecordProcessor (onEmit/forceFlush/shutdown) and forwards synchronously,
// so no batching wrapper is needed (unlike span processors that need batching
// to avoid blocking the hot path).
const logRecordProcessors = bridge.logRecordProcessor ? [bridge.logRecordProcessor] : [];
? [new PiiScrubSpanProcessor(), new BatchSpanProcessor(bridge.spanProcessor as never)]
: [new PiiScrubSpanProcessor()];
// PiiScrubLogRecordProcessor runs FIRST for the same reason.
// SentryLogRecordForwarder forwards synchronously (no batching wrapper needed).
const logRecordProcessors = bridge.logRecordProcessor
? [new PiiScrubLogRecordProcessor(), bridge.logRecordProcessor]
: [new PiiScrubLogRecordProcessor()];
// In-process MeterProvider with no reader/exporter. Sentry metrics ingestion
// is experimental in @sentry/opentelemetry 10.x and not wired here; metrics

View File

@@ -9,7 +9,7 @@ import {
REDACTED_VALUE,
keyContainsPii,
queryParamContainsPii,
} from "./pii-fields";
} from "../otel/pii-fields";
// Minimal structural types matching Sentry's event shape used in scrubbers.
// Using index signatures broad enough to satisfy both ErrorEvent and TransactionEvent.