Files
life-echo/api/app/core/logging.py

67 lines
1.9 KiB
Python
Raw Normal View History

"""
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)