# otel-context _(no submodules)_ ## Purpose `otel-context` extracts the active OpenTelemetry trace context (`trace_id` and `span_id`) from the current OTel context and returns them as lowercase hex strings. This allows `AbstractLogger` to automatically annotate every log record with the correlation IDs of the span in which the log call was made — without requiring callers to pass trace context explicitly. When no span is active or the OTel API is configured with a no-op provider, the function returns an empty object without throwing. ## Features - Reads `trace_id` and `span_id` from the active span via `@opentelemetry/api` - Returns `{}` when no span is active, the span context has all-zero IDs (no-op provider), or the OTel API throws unexpectedly - Never throws — defensive `try/catch` wraps the entire extraction - Zero side effects: pure function, no caching, safe to call on every log line ## Usage: Basic Example ```ts import { getOtelTraceContext } from "@suaveplan/logger/otel"; const traceCtx = getOtelTraceContext(); // When inside an active span: { trace_id: "abc123...", span_id: "def456..." } // When no span is active: {} ``` ## Usage: Advanced Example ```ts import { buildRecord } from "@suaveplan/logger/record"; import { getOtelTraceContext } from "@suaveplan/logger/otel"; // Used internally by AbstractLogger on every log call: const traceCtx = getOtelTraceContext(); const record = buildRecord(level, msg, ctx, ts, traceCtx, errorPayload); // record.trace_id and record.span_id are populated when a span is active ``` ## API Reference ### `getOtelTraceContext(): OtelTraceContext` Returns an object with optional `trace_id` and `span_id` string fields. Returns `{}` when: - No span is active in the current context - The active span has an all-zero trace ID (indicates a no-op OTel SDK) - `@opentelemetry/api` throws for any reason ### `interface OtelTraceContext` ```ts interface OtelTraceContext { trace_id?: string; span_id?: string; } ``` ## Implementation Notes The zero-ID guard (`00000000000000000000000000000000`) exists because the OTel no-op provider returns a valid-looking `SpanContext` with all-zero IDs rather than returning `undefined`. Emitting those zero IDs would mislead log consumers into thinking a real trace exists. The `try/catch` guard exists because OTel API implementations can throw in unusual environments (e.g., incompatible versions, patched globals in test environments).