"""日志配置:控制台 + 文件 + 单 run StringIO Tee。""" import logging import os import sys from datetime import datetime from logging.handlers import RotatingFileHandler from pathlib import Path from app.config import get_settings _settings = get_settings() _LOG_DIR = Path("logs") _LOG_DIR.mkdir(parents=True, exist_ok=True) def setup_logging() -> None: """应用启动时调用一次。""" root = logging.getLogger() root.setLevel(_settings.LOG_LEVEL.upper()) # 避免重复添加 handler(uvicorn 重载时) if root.handlers: return fmt = logging.Formatter( "%(asctime)s | %(levelname)-7s | %(name)s | %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) # 控制台 console = logging.StreamHandler(sys.stdout) console.setFormatter(fmt) root.addHandler(console) # 文件 log_file = _LOG_DIR / f"app-{datetime.now():%Y-%m-%d}.log" file_handler = RotatingFileHandler( log_file, maxBytes=20 * 1024 * 1024, backupCount=10, encoding="utf-8" ) file_handler.setFormatter(fmt) root.addHandler(file_handler) # 调整 uvicorn 噪音 logging.getLogger("uvicorn.access").setLevel(logging.WARNING) logging.getLogger("apscheduler.scheduler").setLevel(logging.INFO) def get_logger(name: str) -> logging.Logger: return logging.getLogger(name)