"""应用日志配置 —— 按功能模块分文件输出,带轮转防爆盘""" import logging import logging.config import os from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent LOG_DIR = PROJECT_ROOT / "logs" def _log(name: str) -> str: return str(LOG_DIR / f"{name}.log") LOGGING_CONFIG: dict = { "version": 1, "disable_existing_loggers": False, "formatters": { "default": { "format": "%(asctime)s | %(levelname)-5s | %(name)s | %(message)s", "datefmt": "%Y-%m-%d %H:%M:%S", }, "brief": { "format": "%(asctime)s | %(levelname)-5s | %(message)s", "datefmt": "%H:%M:%S", }, }, "handlers": { # ── 按功能分文件 ── "handler_article": { "class": "logging.handlers.RotatingFileHandler", "filename": _log("handler_article"), "maxBytes": 10 * 1024 * 1024, "backupCount": 3, "formatter": "default", "encoding": "utf-8", }, "handler_account": { "class": "logging.handlers.RotatingFileHandler", "filename": _log("handler_account"), "maxBytes": 10 * 1024 * 1024, "backupCount": 3, "formatter": "default", "encoding": "utf-8", }, "handler_enqueue": { "class": "logging.handlers.RotatingFileHandler", "filename": _log("handler_enqueue"), "maxBytes": 10 * 1024 * 1024, "backupCount": 3, "formatter": "default", "encoding": "utf-8", }, "domain_supply": { "class": "logging.handlers.RotatingFileHandler", "filename": _log("domain_content_supply"), "maxBytes": 10 * 1024 * 1024, "backupCount": 3, "formatter": "default", "encoding": "utf-8", }, "domain_enqueue": { "class": "logging.handlers.RotatingFileHandler", "filename": _log("domain_enqueue_task"), "maxBytes": 10 * 1024 * 1024, "backupCount": 3, "formatter": "default", "encoding": "utf-8", }, "infra": { "class": "logging.handlers.RotatingFileHandler", "filename": _log("infra"), "maxBytes": 10 * 1024 * 1024, "backupCount": 3, "formatter": "default", "encoding": "utf-8", }, "server": { "class": "logging.handlers.RotatingFileHandler", "filename": _log("server"), "maxBytes": 10 * 1024 * 1024, "backupCount": 3, "formatter": "default", "encoding": "utf-8", }, # ── 控制台(开发时保留)── "console": { "class": "logging.StreamHandler", "formatter": "brief", }, }, "loggers": { # handler — 按业务功能分 3 组 "src.handlers.article_search": { "handlers": ["handler_article", "console"], "level": "INFO", "propagate": False, }, "src.handlers.article_fetch_detail": { "handlers": ["handler_article", "console"], "level": "INFO", "propagate": False, }, "src.handlers.account_fetch": { "handlers": ["handler_account", "console"], "level": "INFO", "propagate": False, }, "src.handlers.account_article_fetch": { "handlers": ["handler_account", "console"], "level": "INFO", "propagate": False, }, "src.handlers.account_article_update": { "handlers": ["handler_account", "console"], "level": "INFO", "propagate": False, }, "src.handlers.demand_enqueue": { "handlers": ["handler_enqueue", "console"], "level": "INFO", "propagate": False, }, # domain "src.domains.content_supply": { "handlers": ["domain_supply", "console"], "level": "INFO", "propagate": False, }, "src.domains.demand_enqueue_task": { "handlers": ["domain_enqueue", "console"], "level": "INFO", "propagate": False, }, # infra "src.infra": { "handlers": ["infra", "console"], "level": "INFO", "propagate": False, }, # server "src.server": { "handlers": ["server", "console"], "level": "INFO", "propagate": False, }, }, # root — 兜底,未匹配的日志走这里 "root": { "handlers": ["console"], "level": "WARNING", }, } def setup_logging() -> None: """初始化应用日志配置,自动创建 logs/ 目录""" os.makedirs(LOG_DIR, exist_ok=True) logging.config.dictConfig(LOGGING_CONFIG)