diff --git a/app/core/config.py b/app/core/config.py index 66e5d2dd..0b2b76b2 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -10,7 +10,7 @@ from typing import Any, Dict, List, Optional, Tuple, Type from dotenv import set_key from pydantic import BaseModel, BaseSettings, validator, Field -from app.log import logger +from app.log import logger, log_settings, LogConfigModel from app.utils.system import SystemUtils from app.utils.url import UrlUtils @@ -244,7 +244,7 @@ class ConfigModel(BaseModel): TOKENIZED_SEARCH: bool = False -class Settings(BaseSettings, ConfigModel): +class Settings(BaseSettings, ConfigModel, LogConfigModel): """ 系统配置类 """ @@ -406,6 +406,8 @@ class Settings(BaseSettings, ConfigModel): # 仅成功更新配置时,才更新内存 if success: setattr(self, key, converted_value) + if hasattr(log_settings, key): + setattr(log_settings, key, converted_value) return success, message return True, "" except Exception as e: @@ -416,8 +418,14 @@ class Settings(BaseSettings, ConfigModel): 更新多个配置项 """ results = {} + log_updated = False for k, v in env.items(): results[k] = self.update_setting(k, v) + if hasattr(log_settings, k): + log_updated = True + # 本次更新存在日志配置项更新,需要重新加载日志配置 + if log_updated: + logger.update_loggers() return results @property diff --git a/app/log.py b/app/log.py index 26a27ae2..c25cbbca 100644 --- a/app/log.py +++ b/app/log.py @@ -5,15 +5,19 @@ from pathlib import Path from typing import Dict, Any, Optional import click -from pydantic import BaseSettings +from pydantic import BaseSettings, BaseModel from app.utils.system import SystemUtils -class LogSettings(BaseSettings): +class LogConfigModel(BaseModel): """ - 日志设置 + Pydantic 配置模型,描述所有配置项及其类型和默认值 """ + + class Config: + extra = "ignore" # 忽略未定义的配置项 + # 配置文件目录 CONFIG_DIR: Optional[str] = None # 是否为调试模式 @@ -29,6 +33,12 @@ class LogSettings(BaseSettings): # 文件日志格式 LOG_FILE_FORMAT: str = "【%(levelname)s】%(asctime)s - %(message)s" + +class LogSettings(BaseSettings, LogConfigModel): + """ + 日志设置类 + """ + @property def CONFIG_PATH(self): return SystemUtils.get_config_path(self.CONFIG_DIR) @@ -124,7 +134,8 @@ class LoggerManager: def __setup_logger(log_file: str): """ 设置日志 - log_file:日志文件相对路径 + + :param log_file:日志文件相对路径 """ log_file_path = log_settings.LOG_PATH / log_file log_file_path.parent.mkdir(parents=True, exist_ok=True) @@ -134,6 +145,8 @@ class LoggerManager: if log_settings.DEBUG: _logger.setLevel(logging.DEBUG) + + # 全局日志等级 else: loglevel = getattr(logging, log_settings.LOG_LEVEL.upper(), logging.INFO) _logger.setLevel(loglevel) @@ -162,6 +175,21 @@ class LoggerManager: return _logger + def update_loggers(self): + """ + 更新日志实例 + """ + _new_loggers: Dict[str, Any] = {} + for log_file, _logger in self._loggers.items(): + # 移除已有的 handler,避免重复添加 + for handler in _logger.handlers: + _logger.removeHandler(handler) + # 重新设置日志实例 + _new_logger = self.__setup_logger(log_file=log_file) + _new_loggers[log_file] = _new_logger + + self._loggers = _new_loggers + def logger(self, method: str, msg: str, *args, **kwargs): """ 获取模块的logger @@ -181,7 +209,7 @@ class LoggerManager: # 获取调用者的模块的logger _logger = self._loggers.get(logfile) if not _logger: - _logger = self.__setup_logger(logfile) + _logger = self.__setup_logger(log_file=logfile) self._loggers[logfile] = _logger # 调用logger的方法打印日志 if hasattr(_logger, method):