The OpenTelemetry metrics signal is entirely absent: OpenTelemetryInstrument.bootstrap() builds a TracerProvider and calls set_tracer_provider, and every binding threads tracer_provider= only. No MeterProvider is ever constructed.
This is not a ninth instrument
CONTEXT.md defines an instrument as one observability concern, and states that a framework subclass is the same instrument bound to a framework, not a second instrument. The metrics signal is the same OpenTelemetry concern, so it belongs as fields on OpenTelemetryConfig inside the existing OpenTelemetryInstrument — zero new cells, zero new extras, zero new free-threading exposure.
The seam is already cut
Three bindings already accept a meter provider and are being handed nothing:
opentelemetry-instrumentation-asgi and -fastapi both take meter_provider= and create duration histograms
faststream.opentelemetry.middleware likewise
FastStreamTelemetryMiddlewareProtocol in faststream_bootstrapper.py:41 already declares meter_provider in its signature, and faststream_bootstrapper.py:159 passes only tracer_provider. Those three frameworks are emitting metrics into a no-op provider today.
OTLPMetricExporter ships inside opentelemetry-exporter-otlp-proto-http, the package the otl-http extra already installs and the free-threaded CI leg already exercises. No new dependency.
Blocked on one decision
Whether an OTLP metrics pipeline and the Prometheus scrape endpoint should both be active by default, and what that means for double-counting request metrics. Per AGENTS.md this is a rejected-alternative question, so it wants an ADR before the PR, not a paragraph in the PR.
Falls out of this
opentelemetry-instrumentation-system-metrics (runtime/process metrics) becomes reachable through the existing opentelemetry_instrumentors config once a MeterProvider exists. Its only native dependency, psutil, publishes cp313t and cp314t wheels, so it is free-threading clean.
The OpenTelemetry metrics signal is entirely absent:
OpenTelemetryInstrument.bootstrap()builds aTracerProviderand callsset_tracer_provider, and every binding threadstracer_provider=only. NoMeterProvideris ever constructed.This is not a ninth instrument
CONTEXT.mddefines an instrument as one observability concern, and states that a framework subclass is the same instrument bound to a framework, not a second instrument. The metrics signal is the same OpenTelemetry concern, so it belongs as fields onOpenTelemetryConfiginside the existingOpenTelemetryInstrument— zero new cells, zero new extras, zero new free-threading exposure.The seam is already cut
Three bindings already accept a meter provider and are being handed nothing:
opentelemetry-instrumentation-asgiand-fastapiboth takemeter_provider=and create duration histogramsfaststream.opentelemetry.middlewarelikewiseFastStreamTelemetryMiddlewareProtocolinfaststream_bootstrapper.py:41already declaresmeter_providerin its signature, andfaststream_bootstrapper.py:159passes onlytracer_provider. Those three frameworks are emitting metrics into a no-op provider today.OTLPMetricExporterships insideopentelemetry-exporter-otlp-proto-http, the package theotl-httpextra already installs and the free-threaded CI leg already exercises. No new dependency.Blocked on one decision
Whether an OTLP metrics pipeline and the Prometheus scrape endpoint should both be active by default, and what that means for double-counting request metrics. Per AGENTS.md this is a rejected-alternative question, so it wants an ADR before the PR, not a paragraph in the PR.
Falls out of this
opentelemetry-instrumentation-system-metrics(runtime/process metrics) becomes reachable through the existingopentelemetry_instrumentorsconfig once aMeterProviderexists. Its only native dependency,psutil, publishes cp313t and cp314t wheels, so it is free-threading clean.