docs: refresh architecture references for OTel migration

This commit is contained in:
2026-05-11 12:18:44 +02:00
parent 81f2477537
commit e43e03cdee
8 changed files with 86 additions and 66 deletions

View File

@@ -38,13 +38,15 @@ Covered areas:
## src/instrumentation/
**Two interfaces:** `ITracer` (in `tracer.interface.ts`) and `ILogger` (in `logger.interface.ts`).
**Substrate:** OpenTelemetry SDK (ADR-017). Sentry is the exporter via `@sentry/opentelemetry`. Feature packages depend only on the interfaces below — no Sentry or OTel SDK imports.
**Three interfaces:** `ITracer` (`tracer.interface.ts`), `ILogger` (`logger.interface.ts`), `IMetrics` (`metrics.interface.ts`).
**Three implementation pairs:**
- `NoopTracer` / `NoopLogger` — pass-through. Default everywhere.
- `SentryTracer` / `SentryLogger` — adapters over `@sentry/nextjs`. Live in `sentry/` subfolder. **The `sentry/` subfolder is the only path in `packages/` permitted to import `@sentry/*`** (R40), with the additional exception of `instrumentation/di/bind-sentry-instrumentation.{ts,test.ts}`.
- `RecordingTracer` / `RecordingLogger` — in `@repo/core-testing/instrumentation`, not here.
- `NoopTracer` / `NoopLogger` / `NoopMetrics` — pass-through. Default everywhere.
- `OtelTracer` / `OtelLogger` / `OtelMetrics` — emit via OTel API (`@opentelemetry/api`, `@opentelemetry/api-logs`). Live in `otel/` subfolder. **The `otel/` subfolder is the only path in `packages/` permitted to import `@opentelemetry/sdk-*` or `@sentry/opentelemetry`** (R52).
- `RecordingTracer` / `RecordingLogger` / `RecordingMetrics` — in `@repo/core-testing/instrumentation`, not here.
**`with-span.ts` + `with-capture.ts`:** two higher-order helpers used at DI binding time to wrap use case + controller factory results. The binders apply them as a sandwich — `withSpan` outermost, `withCapture` between span and factory:
@@ -62,29 +64,33 @@ const wrapped = withSpan(
`withSpan` is pure delegation to `tracer.startSpan`. `withCapture` catches thrown errors, calls `logger.captureException(err, { tags })`, marks the `__sentryReported` flag, and re-throws — but bails if the flag is already set so the inner-most layer wins.
**`reported-flag.ts`:** small module exporting `markReported(err)` and `isReported(err)`. Used by `withCapture` and `SentryLogger`. `RecordingLogger` carries an inlined copy (tooling → core import is disallowed by the boundary rule).
**`reported-flag.ts`:** small module exporting `markReported(err)` and `isReported(err)`. Used by `withCapture` and `OtelLogger`. `RecordingLogger` carries an inlined copy (tooling → core import is disallowed by the boundary rule).
**Symbols:** `INSTRUMENTATION_SYMBOLS.TRACER`, `INSTRUMENTATION_SYMBOLS.LOGGER` (both `Symbol.for(...)` so cross-realm equality holds).
**Symbols:** `INSTRUMENTATION_SYMBOLS.ITracer`, `INSTRUMENTATION_SYMBOLS.ILogger`, `INSTRUMENTATION_SYMBOLS.IMetrics` (all `Symbol.for(...)` so cross-realm equality holds).
**`sentry/scrub.ts`:** PII scrubbers used by every `Sentry.init()` call across the monorepo. Substring-based key matching catches derived names (`userEmail`, `accessToken`, `apiKey`, `ipAddress`). IPv4/IPv6 are also redacted from string values via the `[redacted-ip]` token.
**`otel/pii-fields.ts`:** vendor-neutral PII substring list (`PII_KEY_SUBSTRINGS`, `PII_QUERY_PARAM_SUBSTRINGS`). Used by `otel/pii-scrub-processor.ts` (server) and imported by `sentry/init-client*.ts` (browser).
**`sentry/init-server.ts` + `init-client.ts`:** centralized init helpers (Next.js flavor) that hard-code R31 (`sendDefaultPii: false`), R32/R33 (scrubbers), R34/R35 (replay mask flags), R37 (sample-rate defaults). Apps call these from `instrumentation.ts` / `instrumentation-client.ts`.
**`otel/pii-scrub-processor.ts`:** `PiiScrubSpanProcessor` + `PiiScrubLogRecordProcessor`. Registered FIRST in the OTel processor chain so all downstream exporters (Sentry) see scrubbed data. Replaces Sentry's `beforeSend`/`beforeSendTransaction` hooks on the server side (ADR-017 §7).
**`sentry/init-server-node.ts` + `init-client-react.ts`:** Vite/non-Next variants used by `apps/web-tanstack`. Same R31/R32/R33/R34/R35/R37 posture; uses `@sentry/node` + `@sentry/react` instead of `@sentry/nextjs`.
**`sentry/init-server.ts` + `sentry/init-client.ts`:** centralized init helpers (Next.js flavor). `init-server.ts` calls `Sentry.init` with `sendDefaultPii: false` (R31) — no `beforeSend` hook (PII scrubbed at OTel layer). `init-client.ts` retains `beforeSend`/`beforeSendTransaction` because browser does not use the OTel pipeline.
**`di/bind-noop-instrumentation.ts` + `bind-sentry-instrumentation.ts`:** bind TRACER + LOGGER symbols to a Container. Returns the resolved instances so callers can use them without container lookup.
**`sentry/init-server-node.ts` + `sentry/init-client-react.ts`:** Vite/non-Next variants used by `apps/web-tanstack`. Same posture as their Next.js counterparts.
**`di/bind-noop-instrumentation.ts` + `bind-otel-instrumentation.ts`:** bind ITracer + ILogger + IMetrics symbols to a Container. Returns the resolved instances so callers can use them without container lookup. `bindSentryInstrumentation` kept as a deprecated alias for one release.
**Subpath exports** (`package.json#exports`):
- `./instrumentation` — barrel (interfaces + Noops + withSpan + withCapture + reported-flag helpers + symbols + binders + node/react init helpers)
- `./instrumentation/sentry/init-server` — Next.js server init helper
- `./instrumentation/sentry/init-client` — Next.js client init helper
- `./instrumentation` — barrel (interfaces + Noops + OtelTracer/OtelLogger + withSpan + withCapture + reported-flag + symbols + binders)
- `./instrumentation/otel` — OTel init helper + resource builder barrel
- `./instrumentation/otel/init-server-node``initOtelServerNode` (app bootstrap, server-side OTel SDK)
- `./instrumentation/sentry/init-server` — Next.js server Sentry.init helper
- `./instrumentation/sentry/init-client` — Next.js browser Sentry.init helper
- `./instrumentation/sentry/init-server-node``@sentry/node` server init (TanStack Start)
- `./instrumentation/sentry/init-client-react``@sentry/react` client init (TanStack Start)
- `./instrumentation/sentry/scrub``beforeSend` / `beforeSendTransaction` (used by per-app PII test)
- `./instrumentation/sentry/init-client-react``@sentry/react` browser init (TanStack Start)
**Boundaries:**
- `core-shared/instrumentation/sentry/**` MAY import from `@sentry/*`.
- `core-shared/instrumentation/otel/**` MAY import from `@opentelemetry/sdk-*` and `@sentry/opentelemetry`.
- `core-shared/instrumentation/sentry/**` MAY import from `@sentry/*` (browser init files).
- Everything else in `packages/core-shared/src/` MUST NOT.
- The eslint rule in `core-eslint/base.js` enforces the broader monorepo boundary (R40).
- ESLint rules R40 + R52 in `core-eslint/base.js` enforce the broader monorepo boundary.