FastAPI Logging
Request-scoped logging with dependency injection and automatic correlation.
Basic Setup
from fastapi import FastAPI, Depends
from fapilog.fastapi import FastAPIBuilder, get_request_logger
app = FastAPI(
lifespan=FastAPIBuilder()
.with_preset("fastapi")
.build()
)
@app.get("/users/{user_id}")
async def get_user(user_id: str, logger=Depends(get_request_logger)):
await logger.info("User lookup", user_id=user_id)
return {"user_id": user_id}
This automatically:
Initializes the logger in app.state
Adds
RequestContextMiddlewarefor correlation IDsAdds
LoggingMiddlewarefor request/response loggingSets up graceful shutdown with log flushing
Request-Scoped Logger
from fastapi import FastAPI, Depends
from fapilog import get_async_logger
app = FastAPI()
async def logger_dep():
return await get_async_logger("request")
@app.get("/users/{user_id}")
async def get_user(user_id: str, logger = Depends(logger_dep)):
await logger.info("User lookup", user_id=user_id)
# Log includes request_id automatically via ContextVarsEnricher
return {"user_id": user_id}
Binding HTTP Context to All Logs
If you need HTTP method/path in every log (not just the completion log):
from fastapi import FastAPI, Request
from fapilog import get_async_logger
app = FastAPI()
@app.middleware("http")
async def bind_http_context(request: Request, call_next):
logger = await get_async_logger("api")
with logger.bind(http_method=request.method, http_path=request.url.path):
return await call_next(request)
Log Correlation
All logs during a request share the same request_id:
{"message": "User lookup", "request_id": "abc-123", "user_id": "42"}
{"message": "request_completed", "request_id": "abc-123", "method": "GET", "path": "/users/42", "status": 200}
Query by request_id to see all logs for a request, including the HTTP context from the completion log.
Notes
Use the async logger in FastAPI apps
request_idflows automatically when usingRequestContextMiddleware+ContextVarsEnricherThe completion log has method/path/status—use
request_idto correlateUse
logger.bind()only if you specifically need HTTP context in every log entry
See Also
FastAPI request_id Logging (Cookbook) - Deep dive into concurrency-safe correlation IDs