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

37 lines
6.3 KiB
Markdown

# Итог: список подсетей и чарт «успешные проверки по целям / площадкам» в «Реестре»
План: [2026-10-06_13-11_registry-subnet-select-and-breakdown-chart-plan.md](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) уже работает на этом коде.