from __future__ import annotations import os from dataclasses import dataclass from dotenv import load_dotenv load_dotenv() def _parse_bool(value: str | None, default: bool = False) -> bool: if value is None: return default return value.strip().lower() in {"1", "true", "yes", "on"} @dataclass(frozen=True) class Settings: app_name: str = os.getenv("APP_NAME", "alert-processor") app_host: str = os.getenv("APP_HOST", "0.0.0.0") app_port: int = int(os.getenv("APP_PORT", "8081")) internal_api_token: str = os.getenv("INTERNAL_API_TOKEN", "").strip() require_internal_api_token: bool = _parse_bool( os.getenv("REQUIRE_INTERNAL_API_TOKEN", "true"), default=True, ) redis_enabled: bool = _parse_bool( os.getenv("REDIS_ENABLED", "true"), default=True, ) redis_url: str = os.getenv("REDIS_URL", "redis://127.0.0.1:6379/0").strip() redis_key_prefix: str = os.getenv("REDIS_KEY_PREFIX", "alert").strip() redis_fingerprint_ttl_seconds: int = int( os.getenv("REDIS_FINGERPRINT_TTL_SECONDS", "86400") ) redis_event_ttl_seconds: int = int( os.getenv("REDIS_EVENT_TTL_SECONDS", "604800") ) suppress_enabled: bool = _parse_bool( os.getenv("SUPPRESS_ENABLED", "true"), default=True, ) suppress_window_seconds: int = int( os.getenv("SUPPRESS_WINDOW_SECONDS", "900") ) suppress_apply_to_average: bool = _parse_bool( os.getenv("SUPPRESS_APPLY_TO_AVERAGE", "true"), default=True, ) flap_enabled: bool = _parse_bool( os.getenv("FLAP_ENABLED", "true"), default=True, ) flap_window_seconds: int = int( os.getenv("FLAP_WINDOW_SECONDS", "120") ) flap_threshold: int = int( os.getenv("FLAP_THRESHOLD", "4") ) flap_apply_to_average: bool = _parse_bool( os.getenv("FLAP_APPLY_TO_AVERAGE", "true"), default=True, ) correlation_enabled: bool = _parse_bool( os.getenv("CORRELATION_ENABLED", "true"), default=True, ) correlation_window_seconds: int = int( os.getenv("CORRELATION_WINDOW_SECONDS", "180") ) correlation_suppress_children: bool = _parse_bool( os.getenv("CORRELATION_SUPPRESS_CHILDREN", "true"), default=True, ) matrix_enabled: bool = _parse_bool( os.getenv("MATRIX_ENABLED", "false"), default=False, ) matrix_homeserver_url: str = os.getenv("MATRIX_HOMESERVER_URL", "").strip().rstrip("/") matrix_room_id: str = os.getenv("MATRIX_ROOM_ID", "").strip() matrix_access_token: str = os.getenv("MATRIX_ACCESS_TOKEN", "").strip() matrix_refresh_token: str = os.getenv("MATRIX_REFRESH_TOKEN", "").strip() matrix_oauth_token_endpoint: str = os.getenv("MATRIX_OAUTH_TOKEN_ENDPOINT", "").strip() matrix_oauth_client_id: str = os.getenv("MATRIX_OAUTH_CLIENT_ID", "").strip() matrix_oauth_client_secret: str = os.getenv("MATRIX_OAUTH_CLIENT_SECRET", "").strip() matrix_access_token_expires_in_seconds: int = int( os.getenv("MATRIX_ACCESS_TOKEN_EXPIRES_IN_SECONDS", "300") ) matrix_refresh_margin_seconds: int = int( os.getenv("MATRIX_REFRESH_MARGIN_SECONDS", "60") ) matrix_token_state_file: str = os.getenv( "MATRIX_TOKEN_STATE_FILE", ".matrix_token_state.json", ).strip() matrix_message_type: str = os.getenv("MATRIX_MESSAGE_TYPE", "m.notice").strip() matrix_request_timeout_seconds: float = float( os.getenv("MATRIX_REQUEST_TIMEOUT_SECONDS", "10") ) matrix_verify_tls: bool = _parse_bool( os.getenv("MATRIX_VERIFY_TLS", "true"), default=True, ) mail_enabled: bool = _parse_bool( os.getenv("MAIL_ENABLED", "false"), default=False, ) mail_smtp_host: str = os.getenv("MAIL_SMTP_HOST", "").strip() mail_smtp_port: int = int(os.getenv("MAIL_SMTP_PORT", "587")) mail_smtp_username: str = os.getenv("MAIL_SMTP_USERNAME", "").strip() mail_smtp_password: str = os.getenv("MAIL_SMTP_PASSWORD", "").strip() mail_from: str = os.getenv("MAIL_FROM", "").strip() mail_to: str = os.getenv("MAIL_TO", "").strip() mail_use_starttls: bool = _parse_bool( os.getenv("MAIL_USE_STARTTLS", "true"), default=True, ) mail_use_tls: bool = _parse_bool( os.getenv("MAIL_USE_TLS", "false"), default=False, ) mail_timeout_seconds: float = float( os.getenv("MAIL_TIMEOUT_SECONDS", "15") ) mail_subject_prefix: str = os.getenv( "MAIL_SUBJECT_PREFIX", "[LLM-Zabbix]", ).strip() zabbix_api_enabled: bool = _parse_bool( os.getenv("ZABBIX_API_ENABLED", "false"), default=False, ) zabbix_api_url: str = os.getenv("ZABBIX_API_URL", "").strip() zabbix_api_token: str = os.getenv("ZABBIX_API_TOKEN", "").strip() zabbix_web_url: str = os.getenv("ZABBIX_WEB_URL", "").strip().rstrip("/") zabbix_api_timeout_seconds: float = float( os.getenv("ZABBIX_API_TIMEOUT_SECONDS", "10") ) zabbix_api_verify_tls: bool = _parse_bool( os.getenv("ZABBIX_API_VERIFY_TLS", "true"), default=True, ) zabbix_graph_period_hours: int = int( os.getenv("ZABBIX_GRAPH_PERIOD_HOURS", "1") ) zabbix_graph_timezone: str = os.getenv( "ZABBIX_GRAPH_TIMEZONE", "UTC", ).strip() zabbix_enrich_only_notify: bool = _parse_bool( os.getenv("ZABBIX_ENRICH_ONLY_NOTIFY", "true"), default=True, ) llm_enabled: bool = _parse_bool( os.getenv("LLM_ENABLED", "false"), default=False, ) llm_base_url: str = os.getenv("LLM_BASE_URL", "").strip().rstrip("/") llm_model: str = os.getenv("LLM_MODEL", "").strip() llm_timeout_seconds: float = float( os.getenv("LLM_TIMEOUT_SECONDS", "45") ) llm_verify_tls: bool = _parse_bool( os.getenv("LLM_VERIFY_TLS", "true"), default=True, ) llm_temperature: float = float( os.getenv("LLM_TEMPERATURE", "0.1") ) llm_max_steps: int = int( os.getenv("LLM_MAX_STEPS", "4") ) llm_max_commands: int = int( os.getenv("LLM_MAX_COMMANDS", "4") ) llm_triage_enabled: bool = _parse_bool( os.getenv("LLM_TRIAGE_ENABLED", "false"), default=False, ) llm_triage_cache_ttl_seconds: int = int( os.getenv("LLM_TRIAGE_CACHE_TTL_SECONDS", "3600") ) queue_enabled: bool = _parse_bool( os.getenv("QUEUE_ENABLED", "true"), default=True, ) queue_name: str = os.getenv("QUEUE_NAME", "alert:queue:events").strip() queue_processing_name: str = os.getenv( "QUEUE_PROCESSING_NAME", "alert:queue:processing", ).strip() queue_deadletter_name: str = os.getenv( "QUEUE_DEADLETTER_NAME", "alert:queue:deadletter", ).strip() queue_block_timeout_seconds: int = int( os.getenv("QUEUE_BLOCK_TIMEOUT_SECONDS", "5") ) queue_max_attempts: int = int( os.getenv("QUEUE_MAX_ATTEMPTS", "3") ) queue_dedup_ttl_seconds: int = int( os.getenv("QUEUE_DEDUP_TTL_SECONDS", "86400") ) queue_requeue_processing_on_startup: bool = _parse_bool( os.getenv("QUEUE_REQUEUE_PROCESSING_ON_STARTUP", "true"), default=True, ) correlation_kind_rules_path: str = os.getenv( "CORRELATION_KIND_RULES_PATH", "./config/event_kind_rules.yaml", ).strip() correlation_root_cause_path: str = os.getenv( "CORRELATION_ROOT_CAUSE_PATH", "./config/root_cause_map.yaml", ).strip() audit_enabled: bool = _parse_bool( os.getenv("AUDIT_ENABLED", "true"), default=True, ) audit_key_prefix: str = os.getenv( "AUDIT_KEY_PREFIX", "alert:audit", ).strip() audit_ttl_seconds: int = int( os.getenv("AUDIT_TTL_SECONDS", "604800") ) audit_max_stage_records: int = int( os.getenv("AUDIT_MAX_STAGE_RECORDS", "200") ) llm_correlation_enabled: bool = _parse_bool( os.getenv("LLM_CORRELATION_ENABLED", "false"), default=False, ) llm_correlation_min_confidence: str = os.getenv( "LLM_CORRELATION_MIN_CONFIDENCE", "medium", ).strip().lower() settings = Settings()