"""配置模型与环境变量加载。""" from __future__ import annotations import os from dataclasses import dataclass, field @dataclass class Config: """模块运行配置。所有字段均可通过环境变量覆盖。""" # Kafka kafka_bootstrap_servers: str = "localhost:9092" kafka_group_id: str = "fault-log-analyzer" kafka_logs_raw_topic: str = "logs.raw" kafka_logs_fault_topic: str = "logs.fault" # Elasticsearch es_hosts: list[str] = field(default_factory=lambda: ["http://localhost:9200"]) es_index_pattern: str = "hms-fault-log-{yyyy.MM}" # MySQL mysql_host: str = "localhost" mysql_port: int = 3306 mysql_user: str = "hms" mysql_password: str = "" mysql_db: str = "hms" # Redis redis_url: str = "redis://localhost:6379/0" # API api_host: str = "0.0.0.0" api_port: int = 8080 # 聚类 cluster_eps: float = 0.75 cluster_min_samples: int = 5 cluster_use_sklearn: bool = False # 根因分析 root_cause_window_minutes: int = 5 # 去重窗口(秒) dedup_ttl_seconds: int = 300 # 存储模式:memory(默认,便于离线运行/测试)或真实后端 storage: str = "memory" @classmethod def from_env(cls) -> "Config": """从环境变量构建配置。""" cfg = cls() env = os.environ def _get(name: str, default: str) -> str: return env.get(name, default) cfg.kafka_bootstrap_servers = _get("KAFKA_BOOTSTRAP_SERVERS", cfg.kafka_bootstrap_servers) cfg.kafka_group_id = _get("KAFKA_GROUP_ID", cfg.kafka_group_id) cfg.kafka_logs_raw_topic = _get("KAFKA_LOGS_RAW_TOPIC", cfg.kafka_logs_raw_topic) cfg.kafka_logs_fault_topic = _get("KAFKA_LOGS_FAULT_TOPIC", cfg.kafka_logs_fault_topic) es_hosts = _get("ES_HOSTS", ",".join(cfg.es_hosts)) cfg.es_hosts = [h.strip() for h in es_hosts.split(",") if h.strip()] cfg.es_index_pattern = _get("ES_INDEX_PATTERN", cfg.es_index_pattern) cfg.mysql_host = _get("MYSQL_HOST", cfg.mysql_host) cfg.mysql_port = int(_get("MYSQL_PORT", str(cfg.mysql_port))) cfg.mysql_user = _get("MYSQL_USER", cfg.mysql_user) cfg.mysql_password = _get("MYSQL_PASSWORD", cfg.mysql_password) cfg.mysql_db = _get("MYSQL_DB", cfg.mysql_db) cfg.redis_url = _get("REDIS_URL", cfg.redis_url) cfg.api_host = _get("API_HOST", cfg.api_host) cfg.api_port = int(_get("API_PORT", str(cfg.api_port))) cfg.cluster_eps = float(_get("CLUSTER_EPS", str(cfg.cluster_eps))) cfg.cluster_min_samples = int(_get("CLUSTER_MIN_SAMPLES", str(cfg.cluster_min_samples))) cfg.cluster_use_sklearn = _get("CLUSTER_USE_SKLEARN", "false").lower() in ( "1", "true", "yes", ) cfg.root_cause_window_minutes = int( _get("ROOT_CAUSE_WINDOW_MINUTES", str(cfg.root_cause_window_minutes)) ) cfg.dedup_ttl_seconds = int(_get("DEDUP_TTL_SECONDS", str(cfg.dedup_ttl_seconds))) cfg.storage = _get("STORAGE", cfg.storage) return cfg