A partial log_config (no "version" key) is deep-merged over uvicorn's
default config before our patching, so users pass only their
customizations, e.g. log_config={"loggers": {"myapp": {"level":
"DEBUG"}}}. Previously such dicts crashed at startup: dictConfig
requires a version, and our root entry referenced a "default" handler
that might not exist; that reference is now only added when the handler
exists. The stock default formatter is replaced only when untouched,
so an overlaid fmt survives. Dicts with version and non-dict configs
behave as before. Documented in the README logging section, with tests
under fastapi-vue/tests (each patched config validated through
dictConfig).
The root logger entry patch_log_config adds now uses INFO in dev and
WARNING in production (Python's default), so third-party library INFO
noise stays silent in production while subloggers remain free to
define their own level overrides. A user-supplied root level still
wins (setdefault).
staticfiles now logs via its own module logger instead of
uvicorn.error: the startup stats line shows in dev (root INFO) and is
hidden in production, and it no longer passes through the
uvicorn-quiet filter that silently ate it.
The kanta logger/handler/formatter block is removed: kanta configures
its own event loggers at import time as of its logging rework, and its
diagnostics follow the root logger like any other library.
run() gains access_log (default on) and log_config parameters. When
enabled, uvicorn's own access log is disabled (access_log=False) and
replaced by an ASGI middleware (adapted from the uvicorn access-log
branch) that logs colored request lines, WebSocket open/close pairs,
and pre-accept rejections in open format.
log_config dicts (uvicorn's default or user-supplied) are patched
best-effort via a registered patch pipeline in fastapi_vue.logging:
swapping in our AccessFormatter, routing our output to a private
fastapi_vue.access logger (uvicorn gates its protocol-level access
logging on uvicorn.access.hasHandlers(), so that logger must stay
handlerless), and filtering stock WebSocket handshake chatter from
uvicorn.error. Non-dict or structurally unexpected configs pass
through untouched.
The middleware is installed by patching Config.load/load_app, hooked
into AccessFormatter instantiation so reload/worker subprocesses
(which re-apply log_config without re-calling run()) are covered.