Add the Analytics section: check runs, analytics API and page
Runs (migration 0011): a run groups the cycles of one launch. It opens when an address enters an idle queue, takes everything submitted or re-checked while it is open and is finalized when all its addresses are done; a re-check after that opens a new run, so results of different runs never mix. check_runs, run_results (one result per address and run, with the verdict and the expected and stored check counts), subnets, run_id on ip_queue and checks. Existing data is split into runs at pauses of more than an hour; ingress checks get the validator that held the address (also at write time from now on). Analytics (internal/analytics): figures computed from the stored checks of the latest cycle of each address in the run, as facts next to the verdict: summary, reasons of partial, data quality, subnets, targets and the subnet x target matrix by check type, ingress by site, error classes, validators, and the address lists behind the indicators and error classes. API: analytics runs, report, lists (JSON or CSV), subnet list; run and subnet filters for the registry. Dashboard: /analytics matching the approved mockup (run selector, indicators with address lists and CSV, error-class dialogs, drill-down to the registry), subnet list on /settings. Sidebar: the control-api link state, theme toggle and logout moved to the top, the three dots next to the logo removed, sections grouped. Rebuilt bin/control-api and bin/admin-dashboard to match. Plan, summary and the updated README, API, USAGE, DASHBOARD and ADMIN_CLEANUP docs are in docs/. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
864208238f
commit
b7669c9e41
44 files changed
+4123
-62
No files matched your search
+68
@@ -705,6 +705,10 @@ curl -s -X POST http://<control-api>:8080/api/v1/admin/auto-cycle/stop
|
||||
результаты, поэтому при неполном наборе вердикт может быть хуже, чем «`ok` из
|
||||
`total`».
|
||||
|
||||
Фильтры постраничного режима (только вместе с `limit`): `run` — только адреса,
|
||||
у которых есть результат в этом запуске (см. [«Аналитика запусков»](#аналитика-запусков)); `subnet` — только
|
||||
адреса внутри подсети (CIDR, например `203.0.113.0/24`). Неверный `run` или `subnet` — `400`.
|
||||
|
||||
### `GET /api/v1/admin/registry/{ip}`
|
||||
|
||||
Реестровая запись по одному адресу плюс вся сохранённая история проверок
|
||||
@@ -993,3 +997,67 @@ curl -s "$BASE/api/v1/admin/ips/203.0.113.10" | python3 -m json.tool
|
||||
|
||||
Для полностью автоматизированного локального прогона (без ручных curl)
|
||||
см. `scripts/run-local-e2e.sh` и [docs/LOCAL_E2E.md](LOCAL_E2E.md).
|
||||
|
||||
## Аналитика запусков
|
||||
|
||||
Запуск — одна «партия» проверок. Он открывается, когда адрес попадает в пустую (или полностью обработанную)
|
||||
очередь; пока он открыт, в него входят все добавленные и перепроверяемые адреса. Запуск завершается, когда все его
|
||||
адреса получили итог (`done`, `failed`, `occupied`) либо удалены из очереди. Перепроверка после завершения запуска
|
||||
открывает **новый** запуск, прежний не меняется. Тип запуска: `auto` (скан автоцикла) или `manual`. Для одного адреса
|
||||
в запуске хранится результат его последнего цикла. Для данных, накопленных до появления запусков, запуски выделены по
|
||||
паузам: циклы, которые заканчиваются с промежутком меньше часа, образуют один запуск.
|
||||
|
||||
### `GET /api/v1/admin/analytics/runs`
|
||||
|
||||
Список запусков, новые первыми, для выбора на странице «Аналитика».
|
||||
|
||||
```json
|
||||
[
|
||||
{"id": 2, "kind": "manual", "state": "open", "started_at": "2026-10-03T15:30:00Z", "finalized_at": null,
|
||||
"addresses": 120, "pass": 40, "partial": 80, "fail": 0, "cancelled": 0, "total": 200, "pending": 80},
|
||||
{"id": 1, "kind": "manual", "state": "finalized", "started_at": "2026-10-02T13:46:45Z", "finalized_at": "2026-10-02T22:28:54Z",
|
||||
"addresses": 6440, "pass": 1962, "partial": 4478, "fail": 0, "cancelled": 0, "total": 6440, "pending": 0}
|
||||
]
|
||||
```
|
||||
|
||||
`addresses` — адреса с итогом, `total` — все адреса запуска в очереди, `pending` — ещё в работе.
|
||||
|
||||
### `GET /api/v1/admin/analytics/runs/{id}`
|
||||
|
||||
Все показатели страницы по одному **завершённому** запуску; открытый запуск — `409`, неизвестный — `404`.
|
||||
Считаются проверки последнего цикла каждого адреса в запуске, в том числе пришедшие позже вердикта (как факты).
|
||||
Результат кэшируется, пока данные запуска и список подсетей не менялись.
|
||||
|
||||
| Блок | Содержимое |
|
||||
|---|---|
|
||||
| `run` | `id`, `kind`, `state`, `started_at`, `finalized_at`, `duration_seconds`, `rechecked` (адресов с несколькими циклами в запуске) |
|
||||
| `summary` | `addresses`, `pass`, `partial`, `fail`, `cancelled`; `egress_ok`, `ingress_ok` (адреса, у которых все записанные проверки уровня успешны); `egress_https_any_failed` и `egress_https_all_failed` (хотя бы одна / все https-проверки провалены), `egress_https_all_targets_failed` (все цели полного набора); `ingress_ssh_any_failed`, `ingress_ssh_all_failed`; `addresses_per_minute` |
|
||||
| `reasons` | причины `partial`, каждый адрес один раз: «Только egress», «Ingress и egress», «Egress и неполный набор», «Ingress, egress и неполный набор», «Только неполный набор», «Только ingress»; нулевые не выдаются |
|
||||
| `quality` | `late_failed_checks_at_pass`, `late_failed_addresses_at_pass`, `ingress_failed_checks`, `ingress_failed_late`, `incomplete_addresses`, `pass_with_failed_addresses`, `pass_by_facts` |
|
||||
| `subnets` | по подсети: `cidr`, `label`, `addresses`, `pass`, `egress_ok`, `ingress_ok` (без списка подсетей — группы по /24; адрес вне списка — «прочие») |
|
||||
| `targets` | `types` (семейства egress-проверок), `targets` (хосты, по убыванию провалов https), `failed` (по типу: число адресов с провалом на каждую цель) |
|
||||
| `matrix` | по типу: строки «подсеть × цель» для подсетей с `partial` (`partial`, `percent` по целям) |
|
||||
| `sites` | `types` и строки площадок: `total` и `ok` проверок по типу |
|
||||
| `errors` | классы ошибок проваленных ingress-проверок («SSH: таймаут», «ICMP: нет ответа», …) со счётчиками |
|
||||
| `validators` | по валидатору: `total`, `ok` https-проверок egress |
|
||||
|
||||
Тип проверки — это `check_type` до первого дефиса: `tcp-22` и `tcp-443` дают `tcp`.
|
||||
|
||||
### `GET /api/v1/admin/analytics/runs/{id}/lists/{kind}`
|
||||
|
||||
Таблица адресов за показателем или классом ошибки: `{"kind", "class", "columns": [...], "rows": [[...]]}`.
|
||||
`kind`: `egress_https_any`, `egress_https_all`, `ingress_ssh_any`, `ingress_ssh_all` или `error` (с `?class=SSH: таймаут`;
|
||||
без класса и неизвестный `kind` — `404`). С `?format=csv` — файл CSV (UTF-8 с BOM, `Content-Disposition: attachment`,
|
||||
имя вида `ingress_ssh_all_run1.csv`). Для `error` строка — одна проваленная проверка: адрес, подсеть, площадка,
|
||||
валидатор, вердикт адреса, статус («провал, в вердикте» или «провал, после вердикта»).
|
||||
|
||||
### `GET /api/v1/admin/config/subnets`, `PUT /api/v1/admin/config/subnets`
|
||||
|
||||
Список подсетей, по которым группируются адреса на странице «Аналитика». `PUT` заменяет список целиком:
|
||||
|
||||
```json
|
||||
{"subnets": [{"cidr": "83.166.248.0/21", "label": "москва"}, {"cidr": "10.0.0.0/8"}]}
|
||||
```
|
||||
|
||||
CIDR приводится к канонической записи (`10.1.2.3/24` → `10.1.2.0/24`), повторы схлопываются; неверный CIDR — `400`,
|
||||
список остаётся прежним. Адрес относится к самой узкой подходящей подсети.
|
||||
Reference in new issue
Block a user