FastAPI cookbook · Beginner

Add request IDs and structured logs to FastAPI

Correlate every log line from one request and return the ID to clients for support.

Approach

Middleware reads or generates a request ID, stores it in a contextvars.ContextVar (safe across async tasks), adds it to the response header, and a logging filter injects it into every record. Log JSON with structlog or a JSON formatter.

Solution

import logging, time, uuid
from contextvars import ContextVar
from fastapi import Request

request_id_var: ContextVar[str] = ContextVar("request_id", default="-")


class RequestIdFilter(logging.Filter):
    def filter(self, record: logging.LogRecord) -> bool:
        record.request_id = request_id_var.get()
        return True


handler = logging.StreamHandler()
handler.addFilter(RequestIdFilter())
handler.setFormatter(logging.Formatter('{"ts":"%(asctime)s","level":"%(levelname)s","logger":"%(name)s",'
                                       '"request_id":"%(request_id)s","msg":"%(message)s"}'))
logging.basicConfig(level=logging.INFO, handlers=[handler])
logger = logging.getLogger("app")


@app.middleware("http")
async def request_context(request: Request, call_next):
    rid = request.headers.get("x-request-id") or uuid.uuid4().hex
    token = request_id_var.set(rid[:64])
    start = time.perf_counter()
    try:
        response = await call_next(request)
    finally:
        logger.info("%s %s %.1fms", request.method, request.url.path, (time.perf_counter() - start) * 1000)
        request_id_var.reset(token)
    response.headers["X-Request-ID"] = rid
    return response

Pitfalls

  • Thread-locals in async code (use contextvars).
  • Hand-built JSON format strings break on quotes in messages — prefer structlog or python-json-logger in production.
  • Logging bodies with secrets.

Variations

  • asgi-correlation-id package provides the middleware and filter.
  • OpenTelemetry adds trace IDs to logs automatically.

Further reading: Python: contextvars

Reference: https://docs.python.org/3/library/contextvars.html

More FastAPI recipes