Migrating to v6.0¶
This page covers every breaking change introduced in v6.0 and the steps required to update your code.
Requirements¶
Python >=3.11 is still supported, and 3.15 is added. The minimum versions of these dependencies move up:
| Package | v5 | v6 |
|---|---|---|
sqlalchemy[asyncio] |
>=2.0 |
>=2.1.2 |
fastapi |
>=0.100.0 |
>=0.142.0 |
opentelemetry-api |
not required | >=1.44.0 |
SQLAlchemy 2.1 required¶
Upgrade SQLAlchemy before updating fastapi-toolsets, and follow SQLAlchemy's migration guide for your own code.
No schema change is needed: the UUIDv7Mixin column still defaults to uuidv7().
opentelemetry-api is a dependency¶
The logger reads the current trace and span ids through opentelemetry-api, which is now installed with fastapi-toolsets. It does nothing until a tracer provider is configured. Forwarding log records to OpenTelemetry needs the otel extra (fastapi-toolsets[otel]).
Exceptions¶
Constraint violations answer 409/422 instead of 500¶
init_exceptions_handlers now handles IntegrityError. Unique, foreign key and exclusion violations return 409, not-null and check violations return 422, each with its own error_code (DB-409-UNIQUE, DB-422-NOTNULL, ...). Other integrity errors are still a 500. See Constraint violations.
Clients that treated these 500s as a signal need updating. To keep the previous behaviour, register your own IntegrityError handler after init_exceptions_handlers:
The commit middleware of db.install(app) also answers a failed commit through the app's handler for that error, where it used to end in a 500.
Logger¶
logger.py is now the logger/ package. configure_logging takes a LoggingConfig or a level, plus any of its fields as keyword arguments, and FastAPI applications call init_logging, which also adds the request logging middleware. See the logger module for the new features: request context, access log, trace correlation and the OpenTelemetry bridge.
fmt and logger_name removed¶
Records are rendered by ConsoleFormatter on a terminal and JsonFormatter elsewhere, so a format string no longer applies. configure_logging always configures the root logger, which every named logger propagates to, so logger_name is gone too.
To keep a custom layout, subclass ConsoleFormatter and set it on your own handler, or add a handler with your logging.Formatter to the root logger next to the ones configure_logging installs.
Output moves from stdout to stderr¶
Log lines are written to stderr, leaving stdout to your program's output. Pass stream="stdout" to keep the previous behaviour:
New default line format¶
The console line changed from %(asctime)s - %(name)s - %(levelname)s - %(message)s to a shorter layout with milliseconds, the fields passed through extra=, and the request id:
Outside a terminal, records are JSON objects, one per line. Tools parsing the previous format need updating, or set style="console" and datefmt="%Y-%m-%d %H:%M:%S" to come closer to it.
uvicorn's access log¶
init_logging replaces uvicorn's access log with one structured line per request. Pass access_log=False to keep uvicorn's.
Noisy third-party loggers capped at WARNING¶
asyncio, httpcore, httpx and urllib3 are held at WARNING whatever level you pass, so level="DEBUG" no longer shows their records. Pass quiet=() to let them through, or raise one logger with levels. See Configuration.
Records forwarded to OpenTelemetry when the otel extra is installed¶
With opentelemetry-instrumentation-logging installed, configure_logging adds a handler that emits every record to the OpenTelemetry logger provider. If your app already attaches its own LoggingHandler, records would be exported twice: drop yours, or pass otel=False. See Sending logs to OpenTelemetry.