Middleware Stack
ZodiacCore provides a standard stack of Pure ASGI middlewares for request tracing, latency monitoring, and access logging. They handle HTTP and WebSocket; lifespan scope is passed through unchanged.
1. Core Middlewares
Trace ID Middleware
The TraceIDMiddleware is the entry point for observability. It:
- Reads: Looks for an
X-Request-IDheader in the incoming request (HTTP) or WebSocket upgrade request. - Generates: If missing or invalid (not 36 characters), it generates a fresh UUID.
- Persists: Sets the ID in the request context (via
zodiac_core.context) for the duration of the request or WebSocket connection, then resets it. - Responds: For HTTP, attaches the same ID to the response headers for frontend tracking.
Access Log Middleware
The AccessLogMiddleware records every HTTP request and WebSocket connection. It logs:
- HTTP: Method, path, status code, and processing latency (ms). Trace ID is picked up from context when present.
- WebSocket: Path and latency with a fixed status
101(Switching Protocols). Trace ID is available in context for the connection lifetime. - Lifespan: Not logged; scope is passed through.
2. Usage & Order
The simplest way to use these is via register_middleware.
Middleware Order
ZodiacCore adds middlewares in a specific order to ensure that the Trace ID is generated before the Access Log tries to record it.
from fastapi import FastAPI
from zodiac_core.middleware import register_middleware
app = FastAPI()
# Registers both TraceID and AccessLog middlewares in the correct order
register_middleware(app)
3. Customizing Trace ID Generation
If you want to use a custom header name or a different ID generator (e.g., K-Sorted IDs), you can add the middleware manually:
from zodiac_core.middleware import TraceIDMiddleware
app.add_middleware(
TraceIDMiddleware,
header_name="X-Correlation-ID",
generator=lambda: "my-custom-id-123"
)
4. API Reference
Middleware Utilities
Middleware stack: Trace ID and Access Log.
Implemented as Pure ASGI middleware (no BaseHTTPMiddleware).
Scope types ("http", "websocket", "lifespan") follow the ASGI spec: - https://asgi.readthedocs.io/en/stable/specs/www.html (http, websocket) - https://asgi.readthedocs.io/en/stable/specs/lifespan.html (lifespan)
TraceIDMiddleware
Request ID middleware (Pure ASGI).
- Extracts or generates X-Request-ID.
- Sets it in a ContextVar (zodiac_core.context).
- Appends it to the response headers.
Compatible with: app.add_middleware(TraceIDMiddleware) and app.add_middleware(TraceIDMiddleware, header_name="...", generator=...).
Source code in zodiac_core/middleware.py
AccessLogMiddleware
Access log middleware (Pure ASGI).
Logs method, path, status code, and latency. Uses loguru; request_id appears in logs when TraceIDMiddleware is used (context).
Compatible with: app.add_middleware(AccessLogMiddleware).
Source code in zodiac_core/middleware.py
register_middleware(app)
Register TraceID and AccessLog middlewares in the correct order.
Order: TraceID (outer) then AccessLog (inner), so the access log can include the request_id from context.