Files
cloud-ip-validator/docs/changes/2026-10-06_13-11_registry-subnet-select-and-breakdown-chart-summary.md
T
ayurishchevandClaude Sonnet 5.5 ded196ec8d Registry and Analytics: run, subnet, direction and protocol filters, successes-by-target chart
Registry (/registry):
- filters by run (slice by the address's cycle in that run), subnet
  (drop-down of configured subnets), direction (egress/ingress) and
  protocol (icmp, tcp, ssh, https, tls); status in scope is computed over
  the narrowed checks
- chart "successful checks per target (egress) / site (ingress)" when both
  direction and protocol are chosen; a row opens the list of addresses
  (dialog, CSV)
- API: direction/protocol parameters and run in GET /admin/registry,
  GET /admin/registry/breakdown and /breakdown/list
- subnet filter passes ids as one JSON parameter (SQLite variable limit)

Analytics (/analytics):
- subnet filter recomputes the whole page over the addresses of the run
  inside the subnet; only their checks are read; cache per run and subnet
- direction and protocol focus the page; with both set the registry chart
  is shown
- subnet parameter in GET /admin/analytics/runs/{id} and lists (JSON, CSV)

Docs: plans and summaries in docs/changes, README, API, USAGE.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-06 14:23:48 +03:00

6.3 KiB

Итог: список подсетей и чарт «успешные проверки по целям / площадкам» в «Реестре»

План: 2026-10-06_13-11_registry-subnet-select-and-breakdown-chart-plan.md. Статус: код написан и проверен (gofmt, build, vet, test; страница в headless-браузере на тестовом стенде civ-test с копией боевой БД). Боевой стенд не пересобирался.

Что изменено

  • БД (internal/db): сборка FROM/WHERE фильтра вынесена из ListRegistryPage в registryFilterSQL (список и чарт используют одно условие). Новый queries_registry_breakdown.go: RegistryBreakdown (один GROUP BY по target для egress или по source для ingress, число адресов под фильтром) и RegistryBreakdownList (проверки одной строки, провалы сверху). checks присоединяется через CROSS JOIN: без статистики планировщик выбирал полный перебор checks.
  • API (internal/httpapi): GET /admin/registry/breakdown и GET /admin/registry/breakdown/list (format=csv); общий разбор фильтра для трёх ручек; подписи целей (без схемы и /) и площадок (имя, иначе site-N); строки от большего числа успешных к меньшему. 400 без направления или протокола, 404 на неизвестный ключ. docs/API.md обновлён.
  • Дашборд (internal/dashboard): «Подсеть» — <select> (подсеть из URL вне списка — отдельный пункт; нет настроенных подсетей — список недоступен, ссылка на /settings); блок чарта внутри registry_table (обновляется вместе с таблицей через htmx); static/registry.js — клик по строке открывает диалог аналитики со списком и CSV; прокси /registry/breakdown/list и /registry/breakdown/csv; подсказка, если выбрано только направление или только протокол.
  • Документы: API.md, USAGE.md, README.md.

Исправлено при ревью (по результатам просмотра страницы)

  1. Полосы чарта имели разную длину: колонка с цифрами подбиралась по содержимому строки. Теперь у неё фиксированная ширина (dashboard.css).
  2. На телефоне поля фильтров растягивались по высоте из-за встроенной базы flex (260/300/200 px) в колонке — отключено для #registry-filter; на узком экране полоса чарта переносится под подпись.
  3. В диалоге столбец «Детали» (текст ошибки) был сжат в узкую полосу — задана минимальная ширина.

Проверки

  • gofmt -l пусто; go vet ./..., go test -count=1 ./... — все пакеты ok. Новые тесты: табличный TestRegistryBreakdown… (порядок, срез запуска, подсеть, статус в области, ingress считает проверки, список, ErrNotFound/ErrValidation, Addresses = total списка), API (400, форма, список, CSV, 404), дашборд (select подсети, чарт и прокси), TestScaleSmoke6440.
  • EXPLAIN QUERY PLAN: запросы идут по idx_checks_run / idx_checks_registry_cycle и уникальному индексу checks; полного перебора checks нет.
  • Тестовый стенд (копия боевой БД, 6498 адресов, 1,08 млн проверок): чарт 0,1–1,1 с в зависимости от фильтра (с запуском и без подсети ~0,7–1,1 с), список одной строки ~0,6 с. Цифры сверены с прямым SQL: github.com в запуске 7 — 4296 из 6490, rxmsk tcp — 6460 из 6492.
  • В браузере (headless Chrome): выбор фильтров через htmx, чарт Egress/Ingress, клик по строке открывает диалог (3639 строк, провалы сверху), клик работает и после повторной htmx-замены таблицы, светлая и тёмная темы, ширина 390 px без горизонтальной прокрутки.

Особенности и замечания

  • Запрос диалога строится из data-qs блока чарта (уже проверенные фильтры, без page/per_page), а не из адресной строки.
  • Стенд боевых данных не имеет проверок tls, а на ingress — только icmp, ssh, tcp-22; чарты ingress для https и tls пусты, это ожидаемо.
  • Чарт добавляет к каждому обновлению таблицы запрос порядка 0,1–1,1 с (на этой копии). Если станет много — считать по кнопке.
  • Время в диалоге — UTC (Проверено (UTC)).
  • Тест TestUpsertCheckIfOpenSetsRecordedAt (internal/db, не затронут изменением) нестабилен под нагрузкой: сравнивает метки времени после паузы 5 мс. Падал в двух из ~10 полных прогонов, отдельно проходит. Стоит починить отдельным изменением.

Выкладка

Не выполнена. Нужны пересборка и перезапуск control-api и admin-dashboard; миграций нет. Тестовый стенд civ-test (18081/18091) уже работает на этом коде.