Skip to content

feat(otel): add OTLP logs signal correlated to traces#73

Open
brentrager wants to merge 1 commit into
mainfrom
feat/otlp-logs-signal
Open

feat(otel): add OTLP logs signal correlated to traces#73
brentrager wants to merge 1 commit into
mainfrom
feat/otlp-logs-signal

Conversation

@brentrager

Copy link
Copy Markdown
Contributor

Problem

The observability SDK exports traces and metrics but not logs. App log lines never reach the product's /v1/logs OTLP endpoint, so they can't be viewed alongside — or correlated with — traces.

Solution

Wire the OTel logs signal into setupOtelSdk, reusing the exact traces/metrics plumbing (ADR-100):

  • Same endpointSMOOAI_OBSERVABILITY_ENDPOINT/v1/logs (bootstrap derives it; per-signal OTEL_EXPORTER_OTLP_LOGS_ENDPOINT override honored).
  • Same auth — static _TOKEN or M2M _AUTH_URL/_CLIENT_ID/_CLIENT_SECRET via a new AuthInjectingLogExporter that reuses the per-request Bearer + 401-retry base class (no header snapshot).
  • Same enable path — no new config keys. Logs are only wired when a logs endpoint resolves; otherwise the global LoggerProvider stays the @opentelemetry/api-logs no-op and stdout is unchanged.
  • Standard OTel logs SDK: LoggerProvider + BatchLogRecordProcessor + OTLPLogExporter (http/json, matching the traces exporter protocol). Versions pinned to the existing 0.55.x line — no bumps.
  • App logs emitted through the standard @opentelemetry/api-logs facade become OTLP log records; the logs SDK stamps the active span's trace_id/span_id from context, giving trace↔log correlation for free.
  • flush/shutdown drain the log processor too.

Verification

  • pnpm typecheck clean, pnpm build clean, 66/66 tests pass.
  • New tests: AuthInjectingLogExporter auth + 401-retry + failure paths; logs-signal wiring toggles on the endpoint; and a real-SDK correlation proof (logs-correlation.test.ts) — a log emitted through the api-logs facade inside a real active span carries that span's real 32/16-hex W3C ids via a real LoggerProvider + async-hooks context manager (not stubbed).

🤖 Generated with Claude Code

Wire a LoggerProvider + BatchLogRecordProcessor + OTLP log exporter into
setupOtelSdk, reusing the traces/metrics endpoint, auth, and enable path.
App logs emitted through the standard @opentelemetry/api-logs facade become
OTLP log records stamped with the active span's W3C trace_id/span_id; when no
logs endpoint resolves the global LoggerProvider stays the api-logs no-op and
stdout output is unchanged.

- AuthInjectingLogExporter reuses the per-request Bearer/401-retry base
- bootstrap derives /v1/logs from SMOOAI_OBSERVABILITY_ENDPOINT
- flush/shutdown drain the log processor too
- tests: exporter auth+retry, signal wiring, and a real-SDK correlation proof

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S2bM94GAnVjYSSv1x7HKRB
@changeset-bot

changeset-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 4c0af40

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@smooai/observability Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant