A hack to silence INFO level log chatter from uvicorn, while still doing this via log config.
This commit is contained in:
@@ -104,6 +104,18 @@ class WebSocketChatterFilter(logging.Filter):
|
|||||||
return not msg.startswith(self._PREFIXES)
|
return not msg.startswith(self._PREFIXES)
|
||||||
|
|
||||||
|
|
||||||
|
class UvicornQuietFilter(logging.Filter):
|
||||||
|
"""Silence uvicorn's routine chatter (startup/shutdown lines, etc.).
|
||||||
|
|
||||||
|
Handler-side, not a logger level: uvicorn's ``configure_logging``
|
||||||
|
re-applies ``log_level`` to its loggers after ``dictConfig``, which would
|
||||||
|
override a level lifted in the config dict.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def filter(self, record: logging.LogRecord) -> bool:
|
||||||
|
return not (record.name.startswith("uvicorn") and record.levelno < logging.WARNING)
|
||||||
|
|
||||||
|
|
||||||
_installed = False
|
_installed = False
|
||||||
|
|
||||||
|
|
||||||
@@ -137,14 +149,15 @@ def patch_log_config(log_config, *, access_log: bool = True): # noqa: ANN001, A
|
|||||||
untouched.
|
untouched.
|
||||||
|
|
||||||
Always adds an unreferenced NullHandler whose Formatter instantiation
|
Always adds an unreferenced NullHandler whose Formatter instantiation
|
||||||
loads tracerite in every process uvicorn applies the config in, a
|
loads tracerite in every process uvicorn applies the config in, filters
|
||||||
filter dropping stock uvicorn's WebSocket chatter from ``uvicorn.error``,
|
on the default handler dropping stock uvicorn's WebSocket chatter and
|
||||||
an emoji-level-prefix Formatter in place of uvicorn's stock ``default``
|
routine INFO lines, an emoji-level-prefix Formatter in place of
|
||||||
formatter (a user-supplied one wins), a root logger entry so
|
uvicorn's stock ``default`` formatter (a user-supplied one wins), a root
|
||||||
``logging.info()`` et al. print through the default handler, and a
|
logger entry so ``logging.info()`` et al. print through the default
|
||||||
no-prefix ``kanta`` logger entry (likewise). With ``access_log``,
|
handler, and a no-prefix ``kanta`` logger entry (likewise).
|
||||||
additionally rewires the ``access`` formatter to our Formatter and
|
With ``access_log``, additionally rewires the ``access`` formatter to
|
||||||
attaches its handler to our ``fastapi_vue.access`` logger. We must not
|
our Formatter and attaches its handler to our ``fastapi_vue.access``
|
||||||
|
logger. We must not
|
||||||
attach handlers to ``uvicorn.access``: uvicorn gates its own
|
attach handlers to ``uvicorn.access``: uvicorn gates its own
|
||||||
protocol-level access logging on ``uvicorn.access.hasHandlers()``.
|
protocol-level access logging on ``uvicorn.access.hasHandlers()``.
|
||||||
"""
|
"""
|
||||||
@@ -162,9 +175,11 @@ def patch_log_config(log_config, *, access_log: bool = True): # noqa: ANN001, A
|
|||||||
with suppress(Exception):
|
with suppress(Exception):
|
||||||
filters = config.setdefault("filters", {})
|
filters = config.setdefault("filters", {})
|
||||||
filters["ws_chatter"] = {"()": "fastapi_vue.logging.WebSocketChatterFilter"}
|
filters["ws_chatter"] = {"()": "fastapi_vue.logging.WebSocketChatterFilter"}
|
||||||
|
filters["uvicorn_quiet"] = {"()": "fastapi_vue.logging.UvicornQuietFilter"}
|
||||||
handler_filters = config["handlers"]["default"].setdefault("filters", [])
|
handler_filters = config["handlers"]["default"].setdefault("filters", [])
|
||||||
if "ws_chatter" not in handler_filters:
|
for name in ("ws_chatter", "uvicorn_quiet"):
|
||||||
handler_filters.append("ws_chatter")
|
if name not in handler_filters:
|
||||||
|
handler_filters.append(name)
|
||||||
|
|
||||||
# Emoji level prefixes for ordinary logs, replacing uvicorn's stock
|
# Emoji level prefixes for ordinary logs, replacing uvicorn's stock
|
||||||
# default formatter; a user-supplied default formatter is left alone.
|
# default formatter; a user-supplied default formatter is left alone.
|
||||||
|
|||||||
Reference in New Issue
Block a user