Initial commit: Message Gateway project

- FastAPI приложение для отправки мониторинговых алертов в мессенджеры
- Поддержка Telegram и MAX/VK
- Интеграция с Grafana, Zabbix, AlertManager
- Автоматическое создание тикетов в Jira
- Управление группами мессенджеров через API
- Декораторы для авторизации и скрытия эндпоинтов
- Подробная документация в папке docs/

Автор: Сергей Антропов
Сайт: https://devops.org.ru
This commit is contained in:
2025-11-12 20:25:11 +03:00
commit b90def35ed
72 changed files with 10609 additions and 0 deletions

132
app/core/config.py Normal file
View File

@@ -0,0 +1,132 @@
"""
Конфигурация приложения.
Автор: Сергей Антропов
Сайт: https://devops.org.ru
"""
import os
import logging
from typing import Optional
from pydantic_settings import BaseSettings, SettingsConfigDict
logger = logging.getLogger(__name__)
class Settings(BaseSettings):
"""Настройки приложения из переменных окружения."""
# Telegram настройки
telegram_bot_token: Optional[str] = None
telegram_enabled: bool = True
# MAX/VK настройки
max_access_token: Optional[str] = None
max_api_version: str = "5.131"
max_enabled: bool = False
# Общие настройки мессенджеров
default_messenger: str = "telegram" # По умолчанию Telegram
# Файлы конфигурации
groups_config_path: str = "/app/config/groups.json"
templates_path: str = "/app/templates"
# API ключ для авторизации
api_key: Optional[str] = None
# Grafana настройки
grafana_url: Optional[str] = None
# Zabbix настройки
zabbix_url: Optional[str] = None
# Kubernetes кластер настройки
k8s_cluster_grafana_subdomain: Optional[str] = None
k8s_cluster_prometheus_subdomain: Optional[str] = None
k8s_cluster_alertmanager_subdomain: Optional[str] = None
# Prometheus Pushgateway настройки
pushgateway_url: Optional[str] = None
pushgateway_job: str = "MessageGateway"
# OpenTelemetry настройки
otel_enabled: bool = False
otel_service_name: str = "monitoring-message-gateway"
otel_exporter_otlp_endpoint: Optional[str] = None
otel_exporter_otlp_protocol: str = "http/json"
otel_traces_exporter: str = "otlp_proto_http"
otel_exporter_otlp_insecure: bool = True
otel_python_log_correlation: bool = False
# Jira настройки
jira_enabled: bool = False
jira_url: Optional[str] = None
jira_email: Optional[str] = None
jira_api_token: Optional[str] = None
jira_project_key: Optional[str] = None
jira_default_assignee: Optional[str] = None
jira_default_issue_type: str = "Bug"
jira_mapping_config_path: str = "/app/config/jira_mapping.json"
jira_create_on_alert: bool = True
jira_create_on_resolved: bool = False
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
case_sensitive=False,
extra="ignore",
env_ignore_empty=True
)
def validate_required(self) -> None:
"""Проверка обязательных переменных окружения."""
if not self.telegram_bot_token:
logger.warning("TELEGRAM_BOT_TOKEN не установлен - приложение может не работать")
# Не выбрасываем исключение, чтобы приложение могло запуститься
def get_k8s_grafana_url(self, cluster: str) -> str:
"""Получить URL Grafana для Kubernetes кластера."""
if not self.k8s_cluster_grafana_subdomain:
raise ValueError("K8S_CLUSTER_GRAFANA_SUBDOMAIN не установлен")
return f"{cluster}.{self.k8s_cluster_grafana_subdomain}"
def get_k8s_prometheus_url(self, cluster: str) -> str:
"""Получить URL Prometheus для Kubernetes кластера."""
if not self.k8s_cluster_prometheus_subdomain:
raise ValueError("K8S_CLUSTER_PROMETHEUS_SUBDOMAIN не установлен")
return f"{cluster}.{self.k8s_cluster_prometheus_subdomain}"
def get_k8s_alertmanager_url(self, cluster: str) -> str:
"""Получить URL AlertManager для Kubernetes кластера."""
if not self.k8s_cluster_alertmanager_subdomain:
raise ValueError("K8S_CLUSTER_ALERTMANAGER_SUBDOMAIN не установлен")
return f"{cluster}.{self.k8s_cluster_alertmanager_subdomain}"
# Глобальный экземпляр настроек (валидация отложена до первого использования)
_settings_instance: Optional[Settings] = None
def get_settings() -> Settings:
"""
Получить экземпляр настроек (lazy initialization).
Returns:
Экземпляр Settings.
"""
global _settings_instance
if _settings_instance is None:
_settings_instance = Settings()
return _settings_instance
# Глобальный экземпляр настроек (lazy initialization)
class _SettingsProxy:
"""Прокси для ленивой инициализации settings."""
def __getattr__(self, name):
"""Получить атрибут из settings."""
return getattr(get_settings(), name)
settings = _SettingsProxy()