Set root logger level by dev mode, drop kanta logging config.

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.
This commit is contained in:
2026-09-16 02:22:35 +00:00
parent 22d9fe350b
commit 3a9c5d1674
2 changed files with 7 additions and 20 deletions
+6 -19
View File
@@ -31,6 +31,7 @@ if TYPE_CHECKING:
from uvicorn.lifespan.on import LifespanSendMessage from uvicorn.lifespan.on import LifespanSendMessage
from .accesslog import AccessLogMiddleware from .accesslog import AccessLogMiddleware
from .environ import env
ANSI_ESCAPE_RE = re.compile(r"\x1b\[[0-9;]*m") ANSI_ESCAPE_RE = re.compile(r"\x1b\[[0-9;]*m")
@@ -312,7 +313,8 @@ def patch_log_config(log_config, *, access_log: bool = True): # noqa: ANN001, A
routine INFO lines, an emoji-level-prefix Formatter in place of routine INFO lines, an emoji-level-prefix Formatter in place of
uvicorn's stock ``default`` formatter (a user-supplied one wins), a root uvicorn's stock ``default`` formatter (a user-supplied one wins), a root
logger entry so ``logging.info()`` et al. print through the default logger entry so ``logging.info()`` et al. print through the default
handler, and a no-prefix ``kanta`` logger entry (likewise). The handler, at INFO in dev and WARNING in production (matching Python's
default). The
``watchfiles.main`` logger is lifted to WARNING so its INFO "N changes ``watchfiles.main`` logger is lifted to WARNING so its INFO "N changes
detected" line is dropped while the WARNING "Reloading..." line (logged detected" line is dropped while the WARNING "Reloading..." line (logged
to ``uvicorn.error``) still shows; a user-supplied level wins. to ``uvicorn.error``) still shows; a user-supplied level wins.
@@ -355,9 +357,11 @@ def patch_log_config(log_config, *, access_log: bool = True): # noqa: ANN001, A
# uvicorn's default config leaves the root logger handlerless, eating # uvicorn's default config leaves the root logger handlerless, eating
# logging.info() et al.; route root through uvicorn's default handler. # logging.info() et al.; route root through uvicorn's default handler.
# Level is WARNING in production so third-party loggers stay quiet, as
# with Python's default; dev keeps INFO. Subloggers can override.
with suppress(Exception): with suppress(Exception):
root = config.setdefault("root", {}) root = config.setdefault("root", {})
root.setdefault("level", "INFO") root.setdefault("level", "INFO" if env.dev else "WARNING")
root_handlers = root.setdefault("handlers", []) root_handlers = root.setdefault("handlers", [])
if "default" not in root_handlers: if "default" not in root_handlers:
root_handlers.append("default") root_handlers.append("default")
@@ -369,23 +373,6 @@ def patch_log_config(log_config, *, access_log: bool = True): # noqa: ANN001, A
"level", "WARNING" "level", "WARNING"
) )
# kanta-style output (diffs, colored headers) prints without prefixes,
# like our access log. A user-supplied "kanta" logger entry wins.
with suppress(Exception):
config["formatters"].setdefault("plain", {"fmt": "%(message)s"})
config["handlers"].setdefault(
"plain",
{
"class": "logging.StreamHandler",
"formatter": "plain",
"stream": "ext://sys.stderr",
},
)
config.setdefault("loggers", {}).setdefault(
"kanta",
{"handlers": ["plain"], "level": "INFO", "propagate": False},
)
if access_log: if access_log:
with suppress(Exception): with suppress(Exception):
config["formatters"]["access"] = { config["formatters"]["access"] = {
+1 -1
View File
@@ -21,7 +21,7 @@ from zstandard import ZstdCompressor
from .environ import env from .environ import env
logger = logging.getLogger("uvicorn.error") # Use FastAPI logging style logger = logging.getLogger(__name__)
__all__ = ["Frontend"] __all__ = ["Frontend"]