-
-
Notifications
You must be signed in to change notification settings - Fork 0
Pass exclude_spans to FastAPIInstrumentor so ASGI send/receive spans are opt-out #185
Description
FastAPIOpenTelemetryInstrument.bootstrap() calls:
FastAPIInstrumentor.instrument_app( app=_narrow_app(self.bootstrap_config), tracer_provider=get_tracer_provider(), excluded_urls=",".join(self._build_excluded_urls()), )
instrument_app also accepts exclude_spans: list[Literal["receive", "send"]] (opentelemetry-instrumentation-fastapi, instrument_app signature). Without it, every request produces three spans: the server span plus one each for the ASGI receive and send events. Most users never look at the latter two.
What it costs
Same harness as the sampler issue: async def endpoint, only the OpenTelemetry instrument on, OTLP/HTTP to a local stub sink, in-process ASGI driving. Apple M2, CPython 3.14.7, opentelemetry-instrumentation-fastapi 0.65b0.
| scenario | RPS | μs/req |
|---|---|---|
| as configured today | 7375 | 135.6 |
exclude_spans=["receive", "send"] |
9755 | 102.5 |
| that plus a 1% ratio sampler (other issue) | 15922 | 62.8 |
33 μs/request, a quarter of the instrument's cost, for two thirds of the spans.
Proposal
Add opentelemetry_exclude_spans: list[Literal["receive", "send"]] = [] to OpenTelemetryConfig (or a FastAPI-scoped equivalent) and pass it through.
Worth discussing whether the default should be [] (today's behaviour, no surprise on upgrade) or ["receive", "send"] (cheaper, and matches what most people actually read in a trace view). I lean towards keeping [] and documenting the knob, since dropping spans silently changes what shows up in Jaeger/Tempo for existing users.
Note this parameter is FastAPI-specific; Litestar's instrumentor has its own shape, so the config field may want to live on the FastAPI config rather than the shared one.