Files
Profeto/src/core/config.py
T
WorkBuddy f0c1cc1491 feat(logging): 日志持久化落盘(LOG_FILE 滚动文件)
- LOG_FILE 配置: 空(默认)保持 stdout + Admin 内存日志页(重启清零);
  填路径后额外写 RotatingFileHandler(单文件 10MB × 5 份,utf-8)
- setup_logging 幂等挂载(按 abspath 判重,相对/绝对同文件算一个);
  目录自动创建;文件基础设施失败只 warning 绝不拖垮启动
- docker-compose: api 挂 applogs 卷,默认 LOG_FILE=/app/logs/app.log,
  容器重建日志不丢;.env.example/.gitignore/docs 同步
- tests/test_log_persistence.py: 落盘/幂等/空值禁用/自动建目录/失败降级
- test_p0_standings_cutoff: 匿名约束 name=None 使 any() 子串匹配 TypeError
  (集合顺序不定 → flaky),先判真值再匹配(存量缺陷顺手加固)
2026-09-22 12:18:03 +08:00

88 lines
3.8 KiB
Python

"""pydantic-settings 配置。"""
from __future__ import annotations
from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
# --- app ---
APP_ENV: str = "development"
LOG_LEVEL: str = "INFO"
# 日志持久化:空(默认)只输出 stdout + Admin 内存日志页(重启清零)。
# 填文件路径(如 /app/logs/app.log)后额外写入滚动文件(单文件 10MB × 5 份),
# 进程/容器重启不丢。容器部署需配合 volume 挂载该目录,否则重建仍会丢。
LOG_FILE: str = ""
# P3-3:多 worker 时应用内限流与 KeyRing 各自独立计数(配额放大 N 倍)。
# 设为 True 时若以多 worker 启动 uvicorn 则拒绝启动,避免静默配额漂移。
# 仅在你已前置 Nginx/网关做全局限流、确认不需要此守护时留空/False。
STRICT_SINGLE_WORKER: bool = False
# 生产环境强制要求管理鉴权配置,即使 APP_ENV=production 也生效。
# True 时若 auth_configured() 为 False 则拒绝(503),development 保持 fail-open。
REQUIRE_ADMIN_AUTH: bool = False
# --- database ---
DATABASE_URL: str = "postgresql+asyncpg://football:football@localhost:5432/football"
# --- LLM (OpenAI-compatible) ---
LLM_PROVIDER: str = "openai"
LLM_API_KEY: str = ""
LLM_BASE_URL: str = "https://api.openai.com/v1"
LLM_MODEL: str = "gpt-4o"
LLM_TIMEOUT: int = 60
# multi-agent 分档: 专家用便宜快模型,终裁用强模型;空则回落 LLM_MODEL
LLM_SPECIALIST_MODEL: str = ""
LLM_AGGREGATOR_MODEL: str = ""
# ── 预测缓存 ──
# 预测响应缓存后端:空(默认)=进程内 LRU+TTL 字典;填 redis://host:port/db 启用 Redis。
# Redis 失败自动降级内存缓存并 warning,不中断预测;不强制依赖 redis 包。
# TTL 固定 300s(5 分钟),键格式与内存后端一致(含 prompt 模板 hash)。
PREDICT_CACHE_URL: str = ""
# --- data sources ---
BZZOIRO_KEY: str = ""
BZZOIRO_BASE: str = "https://sports.bzzoiro.com/api/v2"
# --- 代理头信任 ---
# 为 True 时才解析 X-Forwarded-For,否则只用 request.client.host。
# 公网部署时应设为 True,并确保仅 Nginx 等可信反代能访问 API,
# 且 Nginx 层已覆盖真实 IP(X-Real-IP / proxy_protocol)。
TRUST_PROXY_HEADERS: bool = False
# --- CORS ---
CORS_ORIGINS: str = "http://localhost:5173,http://localhost:3000"
CORS_METHODS: str = "GET,POST,PUT,DELETE,OPTIONS"
CORS_HEADERS: str = "Authorization,Content-Type,X-API-Key,Accept"
# --- HTTP ---
HTTP_DEFAULT_TIMEOUT: int = 30
# --- database pool ---
DB_POOL_SIZE: int = 5
DB_MAX_OVERFLOW: int = 10
DB_POOL_TIMEOUT: int = 30
DB_POOL_RECYCLE: int = 1800
# --- 管理接口鉴权 ---
# 管理后台登录密码(POST /api/v1/auth/login),登录后颁发 HttpOnly Cookie 会话。
# 采集 / 回测等高成本或写入型接口同样需要此密码或下方 API Key。
# 两者均留空表示「未启用鉴权」(本地开发默认),生产环境必须至少设置一项。
# 注意:.env 中的 ADMIN_PASSWORD 是初始值;后台修改密码后以数据库中的
# scrypt 哈希为准,建议随后删除此明文项。
ADMIN_PASSWORD: str = ""
ADMIN_API_KEY: str = ""
# 管理后台会话有效期(小时)
ADMIN_SESSION_TTL_HOURS: int = 168
# --- 加密主密钥 ---
# 敏感配置(数据源/LLM 的 API Key)入库加密、会话签名都由它派生。
# 只存于部署机 .env,切勿入库或提交代码。生成: openssl rand -base64 32
# 变更后已加密配置将无法解密(需在后台重新保存)。
SECRET_KEY: str = ""
settings = Settings()