67 lines
1.9 KiB
Python
67 lines
1.9 KiB
Python
"""
|
||
loguru 统一日志配置 + InterceptHandler 拦截标准库 logging。
|
||
"""
|
||
|
||
import logging
|
||
import sys
|
||
|
||
from loguru import logger
|
||
|
||
|
||
class InterceptHandler(logging.Handler):
|
||
"""Route standard-library logging messages into loguru."""
|
||
|
||
def emit(self, record: logging.LogRecord) -> None:
|
||
try:
|
||
level = logger.level(record.levelname).name
|
||
except ValueError:
|
||
level = record.levelno
|
||
|
||
frame, depth = logging.currentframe(), 2
|
||
while frame and frame.f_code.co_filename == logging.__file__:
|
||
frame = frame.f_back
|
||
depth += 1
|
||
|
||
logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())
|
||
|
||
|
||
def setup_logging() -> None:
|
||
"""Call once at application startup, before any other import that logs."""
|
||
logger.remove()
|
||
|
||
logger.add(
|
||
sys.stderr,
|
||
level="INFO",
|
||
format=(
|
||
"<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | "
|
||
"<level>{level: <8}</level> | "
|
||
"<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> | "
|
||
"{extra[request_id]} | "
|
||
"<level>{message}</level>"
|
||
),
|
||
backtrace=True,
|
||
diagnose=False,
|
||
)
|
||
|
||
# 将根 logger 重定向到 loguru,不再使用 basicConfig(文档要求:统一走 loguru)
|
||
root = logging.getLogger()
|
||
root.handlers = [InterceptHandler()]
|
||
root.setLevel(0)
|
||
|
||
for name in (
|
||
"uvicorn",
|
||
"uvicorn.error",
|
||
"uvicorn.access",
|
||
"sqlalchemy.engine",
|
||
"celery",
|
||
"celery.worker",
|
||
):
|
||
logging.getLogger(name).handlers = [InterceptHandler()]
|
||
|
||
logger.configure(extra={"request_id": "-"})
|
||
|
||
|
||
def get_logger(name: str) -> logging.Logger:
|
||
"""获取具名 logger,统一走 loguru 拦截。各模块应使用此函数而非直接 import logging。"""
|
||
return logging.getLogger(name)
|