All posts

FastAPI Logging Best Practices

Set up production-ready logging in FastAPI with structured output, request tracing, middleware integration, and performance monitoring.

FastAPI Logging Best Practices

FastAPI's async nature requires thoughtful logging setup. Here's how to implement production-grade logging.

Configure Structured Logging

Use structlog for JSON-formatted, context-rich logs:

import structlog

structlog.configure(
    processors=[
        structlog.stdlib.filter_by_level,
        structlog.stdlib.add_logger_name,
        structlog.stdlib.add_log_level,
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.processors.StackInfoRenderer(),
        structlog.processors.JSONRenderer(),
    ],
    wrapper_class=structlog.stdlib.BoundLogger,
    logger_factory=structlog.stdlib.LoggerFactory(),
)

logger = structlog.get_logger()

Request Tracing Middleware

Add correlation IDs to every request:

import uuid
from starlette.middleware.base import BaseHTTPMiddleware

class RequestTracingMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request, call_next):
        request_id = request.headers.get("x-request-id", str(uuid.uuid4()))
        structlog.contextvars.clear_contextvars()
        structlog.contextvars.bind_contextvars(request_id=request_id)

        logger.info("request_started",
            method=request.method,
            path=request.url.path,
        )

        response = await call_next(request)
        response.headers["x-request-id"] = request_id

        logger.info("request_completed", status=response.status_code)
        return response

app.add_middleware(RequestTracingMiddleware)

Log Slow Endpoints

import time

@app.middleware("http")
async def log_slow_requests(request, call_next):
    start = time.monotonic()
    response = await call_next(request)
    duration = time.monotonic() - start
    if duration > 1.0:
        logger.warning("slow_request",
            path=request.url.path,
            duration_seconds=round(duration, 3),
        )
    return response

What to Log

  • Request lifecycle — start, completion, duration
  • Business events — user actions, state transitions
  • External calls — database queries, API calls with duration
  • Errors — full context including request parameters

What NOT to Log

  • Passwords, tokens, API keys
  • Personal data (emails, addresses) unless required
  • Request/response bodies in production (too verbose)

Combine structured logging with Bugsly's error tracking for complete observability. When an error occurs, your logs provide the context trail and Bugsly captures the exception with full stack traces.

Try Bugsly Free

AI-powered error tracking that explains your bugs. Set up in 2 minutes, free forever for small projects.

Get Started Free