|
|
||
|---|---|---|
| .github/workflows | ||
| acceptance | ||
| docs | ||
| e2e | ||
| profiles | ||
| public | ||
| routers | ||
| scripts | ||
| specs | ||
| src | ||
| tasks | ||
| test | ||
| tests | ||
| .env.example | ||
| .gitignore | ||
| __init__.py | ||
| agg_catalog.py | ||
| api_metrics.py | ||
| cache.py | ||
| cache_keys.py | ||
| config.py | ||
| errors.py | ||
| hot_cache.py | ||
| http.py | ||
| http_utils.py | ||
| index.html | ||
| inflight.py | ||
| logging_config.py | ||
| main.py | ||
| models.py | ||
| package-lock.json | ||
| package.json | ||
| playwright.config.ts | ||
| profile_schema.py | ||
| profiles.py | ||
| profiles_catalog.py | ||
| prom.py | ||
| README.md | ||
| requirements.txt | ||
| schemas.py | ||
| tsconfig.json | ||
| vite.config.ts | ||
| warmup.py | ||
🛰️ CloudVisor API
CloudVisor — это промежуточный API-слой между Prometheus-экспортером Yandex Cloud и пользовательским UI для визуализации метрик облачной инфраструктуры. Он объединяет несколько источников данных (Prometheus, Redis-кэш, Yandex Cloud Metrics API через экспортёр) и предоставляет единый удобный интерфейс для фронтенда и внешних интеграций.
🚀 Цель проекта
Создать модульную систему, аналогичную CloudAdvisor, но полностью на своей инфраструктуре. Функции:
- централизованный доступ к метрикам Yandex Cloud (через Prometheus API);
- унифицированные модели данных (
vector,matrix); - адаптивное кэширование (Redis);
- профили сервисов (Compute, ALB, PostgreSQL и др.);
- REST API для визуализаций, аналитики и алертинга;
- возможность добавлять новые типы профилей через YAML без изменения кода.
Всё это — бэкенд без UI, но готовый для подключения к любому фронту или Grafana-подобной системе.
⚙️ Архитектура
CloudVisor API общается с внешними контейнерами, которые уже запущены и предоставляют данные:
| Контейнер | Назначение | Порт | Описание |
|---|---|---|---|
prometheus-yc-metrics-exporter |
Prometheus-совместный экспортёр для Yandex Cloud | 9090 |
Запрашивает метрики у Yandex Monitoring API (prometheusMetrics) |
yc-metrics-exporter |
Локальный Flask-сервис (NiceOS), агрегация метрик Yandex Cloud по папкам | 9000 |
Источник метрик для Prometheus |
niceos-redis |
Redis-кэш | 6379 |
Используется CloudVisor API для кэширования ответов Prometheus |
CloudVisor API работает поверх этой инфраструктуры как «умный прокси» и предоставляет:
/api/v1/vm/...— метрики виртуальных машин,/api/v1/meta/...— служебные справочники (метки, серии, имена метрик),/api/v1/profile/...— универсальные эндпоинты для разных сервисов на основе YAML-профилей.
🧩 Обзор фаз разработки
Фаза 0 — Базовая санитария
Цель: очистка и стандартизация. Сделано:
- единые модели данных (
MetricVectorResponse,MetricMatrixResponse); - удалены старые неиспользуемые импорты (
prom_client); - добавлен
trace_idдля всех запросов и единый формат ошибок JSON; - улучшен
/healthz: проверка Redis, Prometheus, экспортёра; - включено логирование и базовые тесты.
Результат: чистая кодовая база с прозрачными контрактами и трассировкой.
Фаза 1 — Контекст (что уже есть)
Настроена связь с существующим бэкендом CloudVisor API:
- FastAPI на
http://localhost:8000 - Redis, Prometheus, Exporter в docker-окружении
- UI получает
/statusи отображает ключевые параметры окружения.
Фаза 1 — Ядро Compute (VM)
Цель: реализовать API для работы с метриками виртуальных машин.
Добавлено:
/api/v1/vm/list— список всех ВМ, найденных в Prometheus;/api/v1/vm/{id}/cpu/instant|range— загрузка CPU (момент и история);/api/v1/vm/{id}/network/range— входящий/исходящий трафик сrate();/api/v1/vm/{id}/overview— сводные метрики ВМ (CPU, сеть, память и др.);/api/v1/summary/instant|range— агрегаты по всем ВМ;- кэш Redis с TTL, флагами
X-From-Cache,X-Stale; - нормализация ответов Prometheus → структурированные JSON.
Результат: полноценный REST API для Compute-метрик, пригодный для UI-дашборда.
Фаза 2 — Meta-слой
Цель: справочная подсистема и introspection Prometheus.
Добавлено:
/api/v1/meta/metrics— список всех имён метрик;/api/v1/meta/labels— список всех лейблов;/api/v1/meta/label/{name}/values— возможные значения конкретной метки;/api/v1/meta/series?match[]=...— time-series для заданных фильтров;- кэш Redis для всех мета-данных;
- единая логика ошибок и
trace_id.
Результат: фронтенд или аналитическая система может динамически строить запросы, зная, какие метки и метрики доступны.
Фаза 3 — Profiles
Цель: универсальный слой абстракции метрик.
Идея: описывать метрики сервисов в YAML-профилях (profiles/*), а API само подставляет PromQL и отдает нормализованные данные.
Реализовано:
-
формат профиля (entity, selector, defaults, metrics, groups);
-
пример профиля
profiles/compute.yamlдля ВМ иprofiles/alb.yamlдля ALB; -
шаблонизация PromQL (
{{id}},{{range_window}}); -
трансформации (
to_percent,scale); -
эндпоинты:
/api/v1/profile/list— список профилей;/api/v1/profile/{entity}/search— поиск сущностей (по метке);/api/v1/profile/{entity}/{id}/overview— сводная метрика по группе;/api/v1/profile/{entity}/{id}/metric/{name}/instant|range— отдельная метрика;/api/v1/profile/_admin/reload— перезагрузка YAML без рестарта;
-
поддержка новых сервисов добавлением YAML без изменения кода.
Результат: универсальный API, где добавление нового сервиса (ALB, PostgreSQL, K8s, Redis, Storage и др.) — это просто новый профиль YAML.
🧠 Как это работает в рантайме
-
Экспортёр (
yc-metrics-exporter) запрашивает метрики у Yandex Monitoring API и отдает их в формате Prometheus. -
Prometheus (
prometheus-yc-metrics-exporter) собирает эти метрики и хранит их во временной БД. -
CloudVisor API выполняет запросы к Prometheus через HTTP API:
- преобразует данные в структурированный JSON (Pydantic);
- кэширует ответы в Redis;
- добавляет трассировку и метаданные;
- агрегирует результаты по профилям и сервисам.
-
Фронтенд (в будущем) обращается к CloudVisor API и получает готовые данные для визуализации.
🧰 Основные зависимости
- FastAPI — фреймворк для API
- httpx — асинхронный HTTP-клиент для Prometheus
- redis.asyncio — кэш
- pydantic / pydantic-settings — модели и конфиг
- PyYAML — для загрузки профилей
- pytest / httpx_mock — тестирование
🧪 Примеры запросов
# Проверить статус сервисов
curl http://localhost:8000/healthz
# Получить список ВМ
curl http://localhost:8000/api/v1/vm/list
# Моментальная загрузка CPU по ВМ
curl http://localhost:8000/api/v1/vm/vm-123/cpu/instant
# История CPU за час
curl "http://localhost:8000/api/v1/vm/vm-123/cpu/range?minutes=60&step_seconds=30"
# Сводные данные ВМ
curl http://localhost:8000/api/v1/vm/vm-123/overview
# Все метрики Prometheus
curl http://localhost:8000/api/v1/meta/metrics
# Все профили
curl http://localhost:8000/api/v1/profile/list
# Перезагрузить YAML-профили (dev)
curl -X POST -H "Authorization: Bearer <TOKEN>" http://localhost:8000/api/v1/profile/_admin/reload
📜 Контракты UI ↔ API
Фронтенд (cloudvisor-ui) использует строгие типы ответов и единый парсер ошибок, чтобы гарантировать стабильные интеграции:
ApiErrorописывает коды и трассировку ошибок бэкенда; клиент бросает этот тип при любых не-2xx ответах и сохраняетtrace_id.- Все запросы читают метаданные кэша (
X-From-Cache,X-Stale,X-Cache-Layer) и отображают их бейджами в UI и dev-оверлее. - DTO для ключевых ручек (
/status,/api/v1/meta/metrics,/api/v1/profile/...) описаны вsrc/types/apiContracts.tsи используются в React Query хукаx. - Тесты (
src/__tests__/contracts.spec.ts) проверяют корректность парсинга ошибок и fallback для невалидного JSON.
⚙️ Конфигурация UI
Укажите базовый URL API через переменную окружения Vite:
VITE_CLOUDVISOR_API_BASE=http://localhost:8000
Граф задач (исполнение)
- Исходный план:
tasks/PLAN.yml - Генерация тикетов:
npm run gen:tasks→ создаётtasks/*/*.md - Скафолдинг кода под тикет:
npm run scaffold <TASK_ID> - Быстрые проверки UI: страница
/checklist(ссылки на ключевые страницы) - DoD checklist:
tasks/TEMPLATE_DOD.md+ раздел Acceptance в каждом тикете
Definition of Done (приёмка)
- Функционал: покрыты 7 сценариев; UI живёт при падении Prometheus (stale).
- Скорость: p95 рендера Overview/Top ≤ 500 мс (прогретый API).
- Достоверность: матрицы совпадают с
/api/v1/query_range(|Δ| ≤ 1e-6/точку). - Экспорт: CSV-wide детерминированный; 1ч/30с/≤50 рядов — ≤ 3 с.
- Диагностика: страница показывает p95/p99, hits, stale share; trace_id в UI.
- UX: i18n (ru/en), A11y ≥95 (axe-smoke без нарушений), понятные ошибки/лоадеры.
- Код: линт/тесты/билд — зелёные;
VITE_CLOUDVISOR_API_BASEнастраивает окружение.
📚 Документация профилей
Список доступных профилей и расшифровка KPI лежат в каталоге profiles/docs. Там описаны варианты метрик для managed-баз данных (PostgreSQL, MySQL, Redis, MongoDB, ClickHouse, Kafka) и состав групп overview.
🧩 Что будет дальше
После трёх фаз CloudVisor API готов стать ядром визуальной системы. Следующие шаги:
- добавить UI (React/Vue + ECharts или Plotly);
- построить ролевую модель и аутентификацию;
- интегрировать алерты и SLA-анализ;
- добавить профили для всех Yandex Cloud сервисов:
profiles/postgresql.yaml,profiles/redis.yaml,profiles/loadbalancer.yaml,profiles/ydb.yaml,profiles/s3.yamlи др.
🔍 Итоговая цель
CloudVisor превращает «сырые» метрики Prometheus/Yandex Cloud в единое API-описание состояния инфраструктуры, понятное как для графиков, так и для аналитики. Он даёт гибкость PromQL, но скрывает её сложность за YAML-профилями, кэшем и нормализацией данных.
🧱 Мини-архитектура (TL;DR)
[Yandex Cloud Monitoring]
↓
[yc-metrics-exporter:9000]
↓
[Prometheus:9090]
↓
[CloudVisor API (FastAPI)]
↓
[Redis Cache:6379]
↓
[Frontend or Analytics Tools]
Проект создаёт основу для собственного CloudAdvisor-подобного инструмента мониторинга, но полностью управляемого и расширяемого в рамках NiceOS-экосистемы.
ниже — «расширенная анатомия» экспортёра NiceOS для Yandex Cloud: что он именно отдаёт, какие гарантии даёт, как устроены метки/формат, как его скрейпит Prometheus, где кэш, какие права нужны, как он ведёт себя при сбоях, и как CloudVisor API это потребляет. Это — дополнение к README и базовой архитектуре.
Что именно мы получаем от экспортёра
1) Что делает экспортёр по факту
-
Достаёт метрики из Yandex Monitoring
prometheusMetrics(REST) по каждому сервису и каждой папке (folder) согласно выбранному режиму (одна папка / список / автодискавери по облаку). -
Склеивает все ответы в единый Prometheus-совместимый текст.
-
Чистит дубли
# HELP/# TYPEпри мультипапочном сборе — чтобы Prometheus не ругался. -
Выдаёт две основные точки:
GET /metrics/all— «всё-по-всем»;GET /metrics/<service>— только один сервис (по всем папкам).
-
Обновляет список папок в фоне (lenient авто-рефреш).
-
Имеет
/healthzдля быстрой диагностики (включаем «глубокую» проверку Monitoring API черезHEALTH_CHECK_DEEP=true).
На практике это — универсальный Prometheus target, который маскирует сложность Yandex API (IAM, постраничность, выбор папок/сервисов, нормализация).
2) Какой именно формат на выходе
Экспортёр отдаёт чистый Prometheus exposition format, готовый к скрейпу. Пример (условный):
# HELP cpu_usage CPU utilization ratio (0..1)
# TYPE cpu_usage gauge
cpu_usage{resource_type="vm",resource_id="vm-123",folder_id="b1f...",job="yc",instance="monitoring.api.cloud.yandex.net"} 0.27 1732259700000
cpu_usage{resource_type="vm",resource_id="vm-456",folder_id="b1f...",job="yc",instance="monitoring.api.cloud.yandex.net"} 0.43 1732259700000
# HELP network_received_bytes_total Total bytes received
# TYPE network_received_bytes_total counter
network_received_bytes_total{resource_type="vm",resource_id="vm-123",nic="eth0",folder_id="b1f..."} 1.8243e+09 1732259700000
...
Особенности:
-
Метки (labels) формируются так, чтобы не терялась принадлежность:
- минимум:
__name__,resource_type,resource_id,folder_id; - часто:
job,instance(источник), плюс доменные (nic,device,code,alb_id,bucketи т.п.).
- минимум:
-
Временные метки — в миллисекундах (как в стандартном экспозиционном тексте).
-
Счётчики (
*_total) и gauge-метрики — в нативных единицах:cpu_usage— как правило, ratio (0..1);- сетевые/дисковые байты — накопительные (
*_bytes_total), для скорости используемrate()в PromQL; - latency — или как гистограмма (
*_bucket), или как агрегаты (зависит от сервиса).
3) Что «гарантируется» экспортёром
-
Единый формат и дедуп служебных строк
HELP/TYPEпри объединении множества папок. -
Стабильная маршрутизация сервисов: список по умолчанию
DEFAULT_SERVICESпокрывает официальные сервисы Monitoring +managed-elasticsearch(legacy). -
Кэширование на стороне экспортёра:
- кэширует собранный сырой Prometheus-текст (TTL
CACHE_DEFAULT_TIMEOUT, по умолчанию 300 с); - экономит лимиты Monitoring API и сглаживает пики скрейпа.
- кэширует собранный сырой Prometheus-текст (TTL
-
Ленивая автоактуализация папок (интервал
FOLDER_REFRESH_INTERVAL, по умолчанию 600 с) с защитой от «дупликата» запросов.
4) Потоки данных и где кэш
[Yandex Monitoring prometheusMetrics]
↑ (IAM, per-folder, per-service)
│
[Экспортёр]
- /metrics/all
- /metrics/<service>
│ (Prometheus exposition text)
↓
[Prometheus]
│ (HTTP scrape)
↓
[CloudVisor API]
- PromQL (HTTP API Prometheus)
- Redis кэш (JSON)
- Экспортёр кэширует сырой текст
/metrics/*. - Prometheus уже держит у себя временной ряд (TSDB).
- CloudVisor API поверх Prometheus отдаёт нормализованный JSON (vector/matrix) с Redis-кэшем на ответы.
5) Как конфигурируется сбор
Режим выбора папок
- Одна папка:
YC_FOLDER_ID - Список:
YC_FOLDER_IDS=b1f...,b1f...,b1f... - Автодискавери по облаку:
YC_CLOUD_IDЭкспортёр запросит Resource ManagerGET /resource-manager/v1/folders?cloudId=...со страницами и соберёт id всех папок.
Какие сервисы тянуть
- По умолчанию —
DEFAULT_SERVICES(полный перечень из Monitoring). - Ограничить:
YC_SERVICES=compute,application-load-balancer,storage(CSV).
Тайминги
REQUEST_TIMEOUT(по умолчанию 10 с) — HTTP таймаут к Yandex API.CACHE_DEFAULT_TIMEOUT(по умолчанию 300 с) — кэш ответов/metrics/*.FOLDER_REFRESH_INTERVAL(по умолчанию 600 с) — рефреш папок.
IAM-права
- На
prometheusMetrics— роль уровняmonitoring.viewer(или шире). - Для авто-дискавери —
resource-manager.viewer(или любая дающаяfolders.listпо облаку).
6) Пример конфигурации Prometheus
scrape_configs:
- job_name: 'yc-all'
metrics_path: /metrics/all
static_configs:
- targets: ['yc-metrics-exporter:9000']
- job_name: 'yc-compute'
metrics_path: /metrics/compute
static_configs:
- targets: ['yc-metrics-exporter:9000']
# Можно заводить отдельные джобы per service для гранулированных ретеншнов/прав/квот
- Для крупной инсталляции разумно делить job’ы по сервисам, чтобы контролировать частоту скрейпа и хранение.
7) Поведение при сбоях и деградациях
| Ситуация | Что делает экспортёр | Что увидит Prometheus | Что потом увидит CloudVisor |
|---|---|---|---|
| Monitoring API недоступен | Возвращает пустой текст или частичный набор; пишет в логи | Серия/метрики пропадут до восстановления | В API появятся «дыры» в рядах; Redis отдаст прошлые ответы (если есть), CloudVisor может пометить X-Stale:true |
| Нет прав IAM | /healthz вернёт ошибку конфигурации; /metrics/* будет почти пустым |
Метрик нет | API вернёт пустые result/ошибку, подсветит проблему в логе |
| Автодискавери не сработал | Падает на старте или остаётся со старым списком | Скрейп идёт по «старому» набору | Видим ограниченный набор сущностей до исправления |
| Медленный Monitoring API | Упрётся в REQUEST_TIMEOUT |
Scrape может быть частично пустым | Лучше поднять TTL кэша на экспортёре и/или снизить частоту скрейпа |
Рекомендации:
- при нестабильной сети увеличить
CACHE_DEFAULT_TIMEOUTи/или уменьшитьscrape_intervalв Prometheus; - иметь отдельный дашборд на
/healthzэкспортёра и логах.
8) Набор сервисов и примеры метрик
Экспортёр поддерживает официальный список DEFAULT_SERVICES (Compute, ALB/NLB, Storage, Managed DB и т.д.). Примеры:
-
Compute (ВМ)
cpu_usage(gauge, 0..1)network_received_bytes_total,network_sent_bytes_total(counter)disk_read_bytes_total,disk_written_bytes_total(counter)- возможны
memory_*(зависит от источника)
-
ALB/NLB
alb_http_requests_total,alb_http_responses_total{code}http_request_duration_seconds_bucket(гистограмма)nlb_bytes_total/nlb_packets_total(варианты)
-
Managed PostgreSQL / MySQL / Redis / MongoDB / ClickHouse / Kafka
- QPS, connections, replication lag, bytes/ops per second (через
rate()), гистограммы latency — зависят от сервиса.
- QPS, connections, replication lag, bytes/ops per second (через
-
Object Storage (S3)
- запросы, коды ответов, трафик (вход/выход), latency (гистограмма при наличии).
Важно: точные имена метрик и лейблов определяет Monitoring для каждого сервиса. Экспортёр не переименовывает метрики — он транзитно их отдаёт (с нормализацией HELP/TYPE). Визуализация и агрегаты делаются на этапе PromQL (в Prometheus/CloudVisor API).
9) Как этим пользуется CloudVisor API
CloudVisor не скрейпит напрямую Monitoring. Он обращается к Prometheus, который уже «съел» экспортёр:
- для «моментальных» значений →
/api/v1/query→ нормализуем вvector; - для «диапазона» →
/api/v1/query_range→matrix; - для сетевых/дисковых счётчиков → всегда
rate([5m]); - для latency гистограмм →
histogram_quantile(0.95, sum by (le)(rate(bucket[5m]))).
CloudVisor поверх этого даёт:
- VM-ручки (
/api/v1/vm/...) — CPU/NET/MEM/DISK поresource_id; - Meta-ручки (
/api/v1/meta/...) — список метрик, меток, серий; - Profiles (
/api/v1/profile/...) — YAML-редактуруемые наборы KPI для любых сервисов.
10) Производительность и объём
CACHE_DEFAULT_TIMEOUTна экспортёре (300 с по дефолту) критично снижает нагрузку на Yandex API — каждый запрос/metrics/*не «бьёт» облако, если есть кэш.- Prometheus TSDB хранит историю и обеспечивает быстрый
query_range. - CloudVisor кэширует уже нормализованный JSON в Redis (короткие TTL 10–60 с), чтобы не повторять одно и то же PromQL.
Для больших инсталляций:
- разбивайте
/metrics/<service>на несколько jobs и снижайте частоту на тяжёлых сервисах; - используйте
scrape_timeout<REQUEST_TIMEOUTэкспортёра, чтобы не создавать «кластер» висящих запросов.
11) Безопасность и доступ
-
Экспортёр сам не требует аутентификации (это — внутренний сервис), но IAM токен обязателен на старте (
YC_TOKEN). -
CloudVisor (позже) прикрывается OIDC/Reverse Proxy (в нашей фазе — без ACL).
-
Внешние порты:
- экспортёр:
9000(/metrics/...,/healthz); - Prometheus:
9090(HTTP API + scrape); - Redis:
6379.
- экспортёр:
docker ps у тебя уже показывает:
6a410b5b7afd niceos/prometheus-yc-metrics-exporter:3.7.3 0.0.0.0:9090->9090 prometheus-yc-metrics-exporter
28fd9a41d2ee niceos/redis:8.2.1 0.0.0.0:6379->6379 niceos-redis
1b7081f15b62 niceos/nicesoft-yc-metrics-exporter:0.1.0 0.0.0.0:9000->9000 yc-metrics-exporter
— этого достаточно, чтобы CloudVisor API «наехал» поверх и начал давать JSON.
12) Трюки и практичные PromQL-«рецепты»
-
Скорость сети ВМ, байты/с:
rate(network_received_bytes_total{resource_type="vm",resource_id="VM"}[5m]) rate(network_sent_bytes_total{resource_type="vm",resource_id="VM"}[5m]) -
CPU как %:
100 * cpu_usage{resource_type="vm",resource_id="VM"} -
P95 по гистограммам:
histogram_quantile(0.95, sum by (le)( rate(http_request_duration_seconds_bucket{service="alb"}[5m]) )) -
Топ-10 ВМ по трафику:
topk(10, sum by (resource_id)( rate(network_received_bytes_total{resource_type="vm"}[5m]) + rate(network_sent_bytes_total{resource_type="vm"}[5m]) ))
13) Траблшутинг экспортёра
-
/healthz:status=error+reason=YC_TOKEN is not set→ не задан IAM.folder discovery failed→ нет правresource-manager.viewerили неверныйYC_CLOUD_ID.- Включите
HEALTH_CHECK_DEEP=true— проверит реальный вызов Monitoring API.
-
Логи при старте:
- печатают фактический
MONITORING_ENDPOINT,RESOURCE_MANAGER_ENDPOINT, количество папок, список сервисов и TTL. - проверяйте «пустые» ответы по сервисам — это не всегда ошибка, иногда действительно нет метрик.
- печатают фактический
-
Если Prometheus жалуется на HELP/TYPE дубли — проверьте, что вы обращаетесь к экспортёру, а не напрямую к Monitoring для каждой папки в разных таргетах (экспортёр уже решает проблему дубликатов).
14) Что это даёт CloudVisor целиком
- Единая точка входа к метрикам Yandex Cloud, независимо от числа папок и сервисов.
- Стабильная таксономия: понятные метки (
resource_id,folder_id, …), к которым можно писать профили. - Снижение нагрузки на Monitoring API и Prometheus за счёт двухуровневого кэширования.
- Быстрый путь к UI: CloudVisor API отдаёт чистые
vector/matrix, фронт рисует графики без «запаха» PromQL. - Расширяемость: новый сервис → добавили YAML-профиль, UI уже умеет его читать.
коротко: экспортёр делает «грязную работу» общения с Yandex Monitoring и выдаёт чистые, консистентные, склеенные метрики для Prometheus. Дальше CloudVisor превращает их в быстрый, аккуратный JSON для любого клиента — от пользовательской панели до внешней аналитики.
CloudVisor API
CloudVisor — это API-слой над Prometheus, который нормализует метрики Yandex Cloud и отдаёт их в удобных JSON-структурах. Он строится поверх экспортёра NiceOS и Prometheus, использует Redis для кэша и поддерживает YAML-профили сервисов (Compute, ALB, DB и т.д.) — чтобы добавлять покрытие без изменения кода.
Зачем это нужно
- Единый интерфейс ко всем метрикам облака, независимо от количества папок и сервисов.
- Удобный формат: JSON
vector/matrixвместо сырого Prometheus текста. - Быстрый отклик: кэш Redis на ответы API + кэш экспортёра на склейку metics.
- Расширяемость через YAML: новые сервисы и KPI подключаются профилями, а не кодом.
- Надёжность: чёткие таймауты/ретраи, health-checks, trace-id, деградация с
staleкэшем.
Что уже крутится (контейнеры)
Из docker ps:
CONTAINER ID IMAGE PORTS NAMES
6a410b5b7afd niceos/prometheus-yc-metrics-exporter:3.7.3 0.0.0.0:9090->9090/tcp prometheus-yc-metrics-exporter
28fd9a41d2ee niceos/redis:8.2.1 0.0.0.0:6379->6379/tcp niceos-redis
1b7081f15b62 niceos/nicesoft-yc-metrics-exporter:0.1.0 0.0.0.0:9000->9000/tcp yc-metrics-exporter
-
yc-metrics-exporter:9000— Flask-экспортёр, тянетprometheusMetricsиз Yandex Monitoring и отдаёт готовый Prometheus exposition text:GET /metrics/all— все сервисы по всем папкам,GET /metrics/<service>— один сервис по всем папкам,GET /healthz— статус токена/дискавери/доступности Monitoring API. Права:monitoring.viewerи (для автодискавери)resource-manager.viewer.
-
prometheus-yc-metrics-exporter:9090— Prometheus, скрейпит экспортёр и хранит ряды. -
niceos-redis:6379— Redis-кэш для ответов CloudVisor API.
CloudVisor API разворачивается отдельно и подключается к этим сервисам.
Как это работает (потоки)
Yandex Monitoring (prometheusMetrics)
↑ (IAM, per folder, per service)
yc-metrics-exporter:9000 → Prometheus exposition text
↓ (scrape)
prometheus-yc-metrics-exporter:9090
↓ (PromQL HTTP API)
CloudVisor API
↓
Redis (кэш JSON)
↓
Фронт/интеграции
- Экспортёр агрегирует запросы к Monitoring API, чистит дубли
# HELP/TYPE, кэширует сырой текст (CACHE_DEFAULT_TIMEOUT). - Prometheus скрейпит экспортёр и даёт быстрый
query/query_range. - CloudVisor API делает PromQL-запросы, нормализует в
vector/matrix, кэширует JSON в Redis (короткие TTL), добавляет трассировку/заголовки.
Поверхностный API (после первых фаз)
-
VM (Compute):
GET /api/v1/vm/listGET /api/v1/vm/{id}/cpu/instant|rangeGET /api/v1/vm/{id}/network/range(черезrate())GET /api/v1/vm/{id}/overview -
Summary:
GET /api/v1/summary/instant|range(суммарные CPU, RX/TX и др.) -
Meta:
GET /api/v1/meta/metrics— список имён метрикGET /api/v1/meta/labels— список лейбловGET /api/v1/meta/label/{name}/valuesGET /api/v1/meta/series?match[]=... -
Profiles (YAML):
GET /api/v1/profile/listGET /api/v1/profile/{entity}/searchGET /api/v1/profile/{entity}/{id}/overviewGET /api/v1/profile/{entity}/{id}/metric/{name}/instant|rangePOST /api/v1/profile/_admin/reload(dev)
Форматы ответов
// Vector
{
"result_type": "vector",
"result": [
{ "metric": {"resource_id":"vm-1", "...":"..."}, "value": {"timestamp": 1732262400.0, "value": 0.37} }
]
}
// Matrix
{
"result_type": "matrix",
"result": [
{
"metric": {"resource_id":"vm-1", "...":"..."},
"values": [
{"timestamp": 1732261800.0, "value": 0.23},
{"timestamp": 1732261830.0, "value": 0.25}
]
}
]
}
timestamp— сек (float).- Счётчики (
*_total) — всегда черезrate([5m])→ «в секунду». - CPU/Memory — gauge (при необходимости преобразуем
ratio→percent). - Заголовки:
X-Trace-Id,X-From-Cache,X-Stale.
Фазы и результаты
Ниже — полный план развития, что делаем на каждой фазе и что появляется.
Фаза 0 — Санитария и выравнивание базы
Задачи
- Почистить рудименты (убрать
prom_client, привести роутеры к единому PrometheusClient). - Единые модели:
MetricVectorResponse,MetricMatrixResponse, нормализацияfrom_prom_*. - Мидлвар трассировки:
X-Trace-Idв каждом ответе. - Единый формат ошибок JSON:
{error, message, trace_id}. /healthz: проверка Redis, Prometheus, экспортёра (опционально), статусok/degraded/error.- OpenAPI описания, валидация query-параметров.
Результат
- Чистая, трассируемая база, пригодная для наращивания.
Фаза 1 — Ядро Compute (ВМ)
Задачи
-
Ручки для ВМ:
/api/v1/vm/list/api/v1/vm/{id}/cpu/instant|range/api/v1/vm/{id}/network/range(RX/TX bps черезrate())/api/v1/vm/{id}/overview
-
Summary:
/api/v1/summary/instant|range(sum cpu / net bps)
-
Redis-кэш: короткие TTL (instant 10–15с, range/overview 15–60с), заголовки
X-From-Cache,X-Stale. -
Обработка таймаутов/ошибок Prometheus (504/502).
Результат
- Полноценный API для Compute метрик — готовая основа для дашборда.
Фаза 2 — Meta-слой
Задачи
/api/v1/meta/metrics— имена метрик (/__name__/values)/api/v1/meta/labels— ключи лейблов/api/v1/meta/label/{name}/values— значения лейбла/api/v1/meta/series?match[]=...— time-series по match[] Все с Redis-кэшем (2–5 минут) и fallback на stale.
Результат
- Интроспекция и справочники для фронта/аналитики.
Фаза 3 — Профили (profiles/*)
Задачи
- YAML-схема профиля:
entity,selector,defaults,metrics,groups. - Шаблоны PromQL (
{{id}},{{range_window}}) + трансформации (to_percent,scale). - Роутеры
profile/*:list,search,{id}/overview,{id}/metric/{name}/instant|range. - Горячая перезагрузка профилей (dev):
POST /profile/_admin/reload.
Результат
- Универсальный слой: новые сервисы добавляются YAML-файлом.
- Готовые профили:
compute.yaml(vm),alb.yamlи др.
Фаза 4 — Покрытие сервисов (волна 1)
Задачи
-
Профили:
compute.yaml— CPU, memory, net, diskapplication-load-balancer.yaml— RPS, 5xx, p95 latencynetwork-load-balancer.yaml— bytes/packets, errorsstorage.yaml(S3) — rps, bytes, errors, latency
-
groups.overviewдля каждого.
Результат
- Полное покрытие базовой инфраструктуры.
Фаза 5 — Managed Databases (волна 2)
Задачи
- Профили:
managed-postgresql.yaml,managed-mysql.yaml,managed-redis.yaml,managed-mongodb.yaml,managed-clickhouse.yaml,managed-kafka.yaml. - KPI: QPS/OPS, connections, replication lag, memory/storage usage, latency quantiles (если есть bucket).
Результат
- Покрытие управляемых БД и брокеров.
Фаза 6 — Kubernetes/Serverless
Задачи
managed-kubernetes.yaml: node cpu/mem, pod counts, restarts, evictions, API server requests.serverless-functions.yaml/serverless-containers.yaml/serverless-apigateway.yaml: invocations, errors, duration p95, throttles.
Результат
- Набор профилей для контейнерной и безсерверной нагрузки.
Фаза 7 — Агрегаты
Задачи
/api/v1/agg/{domain}/top?metric=&order=&limit=&minutes=Топ-N сущностей по KPI (например, топ ВМ по трафику)./api/v1/agg/cost-hints(черновик) — агрегаты, близкие к стоимости.
Результат
- Готовые «сводки» без сложного PromQL на клиенте.
Фаза 8 — Экспорт
Задачи
POST /api/v1/export/matrix— NDJSON/CSV/Parquet выгрузка диапазонов.- Лимиты по окну/рядам, стриминг, лог сигнатур запросов.
Результат
- Удобный оффлайн-экспорт для анализа.
Фаза 9 — Производительность/Надёжность
Задачи
- In-memory LRU поверх Redis, объединение in-flight запросов.
- Настройки таймаутов/ретраев/keep-alive.
- Прогрев «summary/overview» кэшей.
- Метрики самого API:
/metrics(Prometheus формат) — latency, cache hits, backend errors.
Результат
- Малые задержки, предсказуемость, наблюдаемость API.
Фаза 10 — Безопасность
Задачи
- OIDC/OAuth2 за reverse-proxy.
- RBAC по профилям и папкам.
- Rate limiting и аудит.
Результат
- Готовность к production-экспозиции.
Фаза 11 — Документация и SDK
Задачи
- Детальные docs по профилям и PromQL-cookbook.
- TypeScript SDK из OpenAPI.
- Примеры Grafana dashboards на CloudVisor API.
Результат
- Проект «самообъясняется» и легко внедряется.
Фаза 12 — Готовность к UI
Задачи
- Убедиться, что
overview/top/meta/exportзакрывают сценарии интерфейса. /statusс версиями:api_version,profiles_revision,prometheus_url.
Результат
- Безболезненная интеграция любого UI.
Конфигурация CloudVisor API
Переменные окружения (минимум):
CLOUDVISOR_PROM_URL=http://prometheus-yc-metrics-exporter:9090
CLOUDVISOR_REDIS_URL=redis://niceos-redis:6379/0
CLOUDVISOR_ALLOWED_ORIGINS_RAW=*
CLOUDVISOR_REQUEST_TIMEOUT_SECONDS=5.0
CLOUDVISOR_CACHE_TTL_SECONDS=30
PROFILE_DIR=./profiles
Для dev:
PROFILE_RELOAD_ENABLED=true
PROFILE_RELOAD_TOKEN=<secret>
Типовые PromQL-рецепты (в API применяются автоматически)
-
Сеть (байты/с):
rate(network_received_bytes_total{...}[5m])rate(network_sent_bytes_total{...}[5m]) -
CPU (%):
100 * cpu_usage{...}(если метрикаratio) -
Диск (байты/с по устройствам):
sum by (device)(rate(disk_read_bytes_total{...}[5m]))sum by (device)(rate(disk_written_bytes_total{...}[5m])) -
Latency p95:
histogram_quantile(0.95, sum by (le)(rate(http_request_duration_seconds_bucket{...}[5m])))
Примеры запросов
# Здоровье
curl http://localhost:8000/healthz
# Compute: список ВМ
curl http://localhost:8000/api/v1/vm/list
# CPU текущий/история
curl http://localhost:8000/api/v1/vm/vm-123/cpu/instant
curl "http://localhost:8000/api/v1/vm/vm-123/cpu/range?minutes=60&step_seconds=30"
# Сеть
curl "http://localhost:8000/api/v1/vm/vm-123/network/range?minutes=60&step_seconds=30"
# Сводка
curl http://localhost:8000/api/v1/summary/instant
curl "http://localhost:8000/api/v1/summary/range?minutes=60&step_seconds=30"
# Meta
curl http://localhost:8000/api/v1/meta/metrics
curl http://localhost:8000/api/v1/meta/labels
curl http://localhost:8000/api/v1/meta/label/resource_id/values
curl "http://localhost:8000/api/v1/meta/series?match[]=cpu_usage{resource_type=\"vm\"}"
# Profiles
curl http://localhost:8000/api/v1/profile/list
curl "http://localhost:8000/api/v1/profile/vm/vm-123/overview?minutes=60&step_seconds=30"
curl http://localhost:8000/api/v1/profile/vm/vm-123/metric/cpu_usage/instant
Нефункциональные требования (в UI)
- Скорость: p95 рендера Overview/Top ≤ 500 мс при тёплом кэше.
- Стабильность: при
X-Stale:trueUI не падает, помечает данныеstale. - TTL (React Query staleTime):
- meta: 120–300 s
- overview/range: 15–30 s
- instant: 10–15 s
- agg: 30–60 s
- Отмена/таймауты:
AbortController+ общий timeout 5s. - Повторы: до 2, без 4xx, с backoff+jitter.
- Безопасность: без секретов, никакого raw HTML, логирование без шума.
- Диагностика: страница Diagnostics показывает p50/p95 рендера, cache hits/stale из
/metrics.
Ошибки и заголовки
- Любой ответ содержит
X-Trace-Id. - Кэш:
X-From-Cache: true|false, устаревший кэш:X-Stale: true|false. - Ошибки — JSON:
{ "error": "prometheus_timeout", "message": "upstream timeout after 5.0s", "trace_id": "..." }
Что получаем в итоге
- Универсальный API мониторинга поверх Yandex Cloud, без жёсткой привязки к конкретному UI.
- Гибкость PromQL остаётся, но скрыта в YAML-профилях; расширять можно без релиза кода.
- Производительность за счёт двух уровней кэша (экспортёр и Redis), аккуратных TTL и объединения запросов.
- Надёжность через health-checks, единый формат ошибок, трассировку запросов и метрики самого API.
- Масштабируемость: новые сервисы покрываются профилями (
profiles/*) — Compute, LB, Storage, Managed DB, Kubernetes, Serverless и т.д.
TL;DR: CloudVisor превращает «сырые» прометеевские ряды Yandex Cloud в стабильный, быстрый и расширяемый JSON-API, готовый для панелей, алертов и интеграций.