44 lines
1.6 KiB
Python
44 lines
1.6 KiB
Python
"""Console logging setup."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
import sys
|
|
|
|
_FORMAT = "%(asctime)s %(levelname)-7s %(name)-28s %(message)s"
|
|
_DATEFMT = "%H:%M:%S"
|
|
|
|
|
|
def ensure_utf8_stdout() -> None:
|
|
"""Make stdout/stderr able to print non-ASCII on a Windows console.
|
|
|
|
Windows terminals default to a legacy code page (cp1252 in Western locales),
|
|
and printing a single Chinese character raises UnicodeEncodeError. The robot's
|
|
own documentation and error strings are Chinese, so an error response would
|
|
otherwise crash the log call that was trying to report it - turning a handled
|
|
failure into an unhandled one.
|
|
"""
|
|
for stream in (sys.stdout, sys.stderr):
|
|
try:
|
|
if stream is not None and hasattr(stream, "reconfigure"):
|
|
stream.reconfigure(encoding="utf-8", errors="replace") # type: ignore[union-attr]
|
|
except Exception: # pragma: no cover - never let logging setup fail
|
|
pass
|
|
|
|
|
|
def configure_logging(level: str = "info") -> None:
|
|
ensure_utf8_stdout()
|
|
numeric = getattr(logging, level.upper(), logging.INFO)
|
|
handler = logging.StreamHandler(sys.stdout)
|
|
handler.setFormatter(logging.Formatter(_FORMAT, datefmt=_DATEFMT))
|
|
|
|
root = logging.getLogger()
|
|
root.handlers = [handler]
|
|
root.setLevel(numeric)
|
|
|
|
# Access logs for a single-user local dashboard are noise.
|
|
logging.getLogger("uvicorn.access").setLevel(logging.WARNING)
|
|
logging.getLogger("httpx").setLevel(logging.WARNING)
|
|
logging.getLogger("httpcore").setLevel(logging.WARNING)
|
|
logging.getLogger("websockets").setLevel(logging.WARNING)
|