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 responseWhat 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
Track up to 100 issues per month on the free plan; events are not billed.
Get Started FreeRelated Articles
Nuxt Production Best Practices
Essential Nuxt best practices for production covering SSR configuration, caching strategies, security headers, and deployment optimization.
Read moreSwift Performance Monitoring Best Practices
Monitor Swift application performance with Instruments profiling, memory tracking, network performance, and real-time crash reporting.
Read moreKotlin Production Best Practices
Essential Kotlin best practices for production including null safety, coroutine patterns, sealed classes for errors, and testing strategies.
Read moreLog Levels Explained: DEBUG, INFO, WARN, ERROR — When to Use Each
A practical guide to choosing the right log level — with framework-specific mappings for Python, Java, Node.js, and Go.
Read moreFrom the same team
SEOBolt
Technical SEO and AI search audits with ready-to-apply fix plans.
Try SEOBolt →GrowFast
Domain in, qualified B2B leads out, with cold outreach and deliverability handled.
Try GrowFast →AutoShort
Turn a topic into a faceless short: AI script, voiceover and captions.
Try AutoShort →RemixViral
Paste a long video and get back the moments worth posting, cut vertical and captioned.
Try RemixViral →