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.
FastAPIOpenTelemetryInstrument.bootstrap()calls:instrument_appalso acceptsexclude_spans: list[Literal["receive", "send"]](opentelemetry-instrumentation-fastapi,instrument_appsignature). Without it, every request produces three spans: the server span plus one each for the ASGIreceiveandsendevents. Most users never look at the latter two.What it costs
Same harness as the sampler issue:
async defendpoint, 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.exclude_spans=["receive", "send"]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"]] = []toOpenTelemetryConfig(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.