Files
suaveplan/openspec/changes/enterprise-testing-integration-otel-collector/proposal.md
2026-05-27 23:29:53 +01:00

4.5 KiB

Why

Section 4 of the test-suite audit (/mnt/s/web/genesis/docs/superpowers/specs/2026-04-25-test-suite-audit.md) flags that observability of the test suite itself is absent: every @suaveplan/* package ships OTel instrumentation via @opentelemetry/api, but there is no fixture that exercises the export path end-to-end and no runner hook that turns each it/test into a span. Today CI can only assert "no SDK registered = no-op"; there is no way to verify that a counter, histogram, or span actually reaches a collector when one is registered. Section 1 of the same audit lists the OpenTelemetry collector as a critical missing service-fixture (alongside OIDC, Mongo, Kafka/NATS).

This change closes both gaps in a single capability: a @suaveplan/testing-integration-otel-collector plugin (a ServiceFixture for otel/opentelemetry-collector-contrib) plus a normative requirement on the testing capability that the runner SHALL emit a span per test, an event per assertion failure, and an event per fixture lifecycle transition when an OTLP endpoint is configured. Failed-test span trees are serialised to playwright-report/traces/ and uploaded to a configured Garage S3 sink — directly addressing audit §4 ("Trace-on-failure exists locally but is not exported anywhere").

What Changes

New plugin package — @suaveplan/testing-integration-otel-collector

  • Lives at packages/testing/testing-integration-otel-collector (mirrors the testing-integration-* plugin convention from CLAUDE.md).
  • Implements the ServiceFixture<TConfig> interface from @suaveplan/testing-integration with image otel/opentelemetry-collector-contrib pinned to a specific minor (digest-pin tracked in tasks.md).
  • Env-bridge: OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_PROTOCOL (http/protobuf default, grpc opt-in), optional OTEL_EXPORTER_OTLP_HEADERS.
  • HTTP healthcheck on :13133/health/status (port configurable; default timeout 60 s).
  • Config object { receivers: ('otlp-grpc' | 'otlp-http')[]; exporters: ('logging' | 'memory' | 'jaeger' | 'file')[]; configFile?: string } — when no configFile is provided the plugin synthesises a minimal otelcol-config.yaml from the receivers/exporters lists.
  • Public helper getSpans({ filter }) queries the in-memory exporter (when configured) and returns ReadableSpan[] for assertion in tests.
  • Errors prefixed INTEGRATION.OTEL_COLLECTOR.*; injectable containerFactory and fetchFn for unit-testability of the fixture itself.

Test-execution OTel export — addition to the testing capability

When OTEL_EXPORTER_OTLP_ENDPOINT is set the test runner SHALL emit one span per it/test (name, status, attributes={ suite, file, retry }), one event per assertion failure (exception.type, exception.message, exception.stacktrace), and one event per fixture lifecycle transition (setup-start, setup-end, teardown-start, teardown-end). Implementation hooks ship at @suaveplan/testing/reporters/otel for both vitest and bun-test. Failed tests serialise their full span tree to playwright-report/traces/<spec>.json and (when TESTING_TRACE_SINK_URL is set) upload that file to the configured Garage S3 bucket.

Capabilities

New Capabilities

  • testing-integration-otel-collector — a ServiceFixture for the OpenTelemetry collector (image policy, env-bridge, health-check contract, config shape, span-query helper, error code prefix).

Modified Capabilities

  • testing — adds the Test-execution OTel export requirement (runner emits spans/events for tests and fixture lifecycle, trace-on-failure serialised and uploaded).

Impact

  • Affected code: new package at /mnt/s/web/genesis/packages/testing/testing-integration-otel-collector/**; new reporters at /mnt/s/web/genesis/packages/testing/testing/src/reporters/otel/**.
  • Affected consumers: every @suaveplan/* test suite gains span export when the env var is set; zero behaviour change when unset.
  • Catalog additions (root package.json): none — @opentelemetry/sdk-node, @opentelemetry/sdk-trace-node, and @opentelemetry/exporter-trace-otlp-http are added under catalogs.observability only if not already pinned by @suaveplan/opentelemetry.
  • Pre-publish gate: plugin package must hit 100% Istanbul coverage (per openspec/AGENTS.md §7) and pass the standard lint typecheck test suite before publish.
  • Cross-cutting: the testing spec gains a new requirement; folding on archive will append it to openspec/specs/testing/spec.md.