Description
Hi. Sorry if this is the wrong channel to report this, I'm not entirely sure if what I'm seeing is incorrect behavior or if I'm holding it wrong.
I'm trying to autoinstrument a FastAPI application served through uvicorn with traces and metrics. I'm aware of the issues with autoinstrumentation around the forking model, so I've abandoned the opentelemetry-instrument
tool and am currently trying to autoinstrument post-fork by calling the opentelemetry.instrumentation.auto_instrumentation.initialize
function in my application code.
I've noticed that if I call initialize()
after importing FastAPI, I get no traces for my FastAPI routes. If I call it before the import, however, I do get the traces working correctly. Other instrumentations like psycopg, aiohttp and redis still work regardless of import order. I don't get any errors in the logs (other than the line about skipping Starlette instrumentation due to version mismatch, but I get it in both cases so it's probably not related).
# works: traces for route handlers
from opentelemetry.instrumentation.auto_instrumentation import initialize
initialize()
from fastapi import APIRouter, FastAPI, Request, Response
# doesn't work: no traces for route handlers
from fastapi import APIRouter, FastAPI, Request, Response
from opentelemetry.instrumentation.auto_instrumentation import initialize
initialize()
pyproject.toml dependencies:
"fastapi[standard]==0.112.2",
"psycopg[binary,pool]>=3.2.3,<4",
"redis[hiredis]>=5.1.0,<6",
"aiohttp[speedups]>=3.10.10,<4",
"opentelemetry-distro==0.54b1",
"opentelemetry-exporter-otlp>=1.33.1,<2",
"uvloop>=0.21.0,<0.22",
Relevant Dockerfile sections:
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --frozen --no-install-project --no-dev
RUN uv run opentelemetry-bootstrap --action=requirements >requirements.txt && \
uv pip install -r requirements.txt
FROM python:3.13-slim-bookworm
WORKDIR /app
COPY --from=builder /app /app
COPY ./src ./src
ENV PATH="/app/.venv/bin:$PATH"
CMD ["uvicorn", "--reload", "--loop", "uvloop", "--host", "0.0.0.0", "--port", "8000", "--app-dir", "src", "--factory", "my_project.app_factory:make_app"]
Activity
[-]Programmatic autoinstrumentation of FastAPI fails depending on initialization order[/-][+]Programmatic autoinstrumentation of FastAPI fails depending on import order[/+]yamplum commentedon May 29, 2025
Looking deeper into it, I see that the other modules get instrumented by wrapping runtime calls, whereas FastAPI gets instrumented by performing a class replacement. I guess my question is, what is the intended way to do instrumentation here? Should I not rely on
initialize()
and manually instrument my dependencies, or is there a better way? Maybe the FastAPI instrumentation method is too aggressive?xrmx commentedon May 29, 2025
@yamplum auto-instrumentation is supposed to run before your code so yeah the first hunk is the correct one. Said that we're trying to make things work on more cases so as you spotted there are some room for improvements on how the fastapi instrumentor works.
yamplum commentedon May 30, 2025
I see, thank you. It's a bit unfortunate that the semantics for autoinstrumentation aren't precisely defined, but works for me. Hopefully this can help someone else struggling with the same problem.