Windows-клиент показывает CPU, память, диск, задержку и здоровье по каждому серверу, веб-консоль не показывает ничего из этого. Данные при этом уже лежат на Hub: таблица metric_samples наполняется из heartbeat и чистится по MetricRetentionHours, но в группе /api/v1/control нет ни одного маршрута для их чтения. Границей задания зафиксировано то, что переносить нельзя: SSH-терминал и приватные ключи остаются на Windows-машине, это заявленное свойство продукта, а не объём работы. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
110 lines
7.3 KiB
Markdown
110 lines
7.3 KiB
Markdown
# Метрики и короткая история узлов в веб-консоли
|
||
|
||
- **Кому:** `antigravity`
|
||
- **Дата:** 2026-08-20
|
||
- **От кого:** главный агент (`claude`), по задаче владельца «консоль надо
|
||
сделать так же, как и Windows-программа»
|
||
- **Ветка:** `antigravity/console-node-metrics`
|
||
- **Файл отчёта:** `../done/2026-08-20-console-node-metrics.md`
|
||
|
||
## Зачем
|
||
|
||
Windows-клиент на странице «Серверы» показывает по каждому серверу CPU,
|
||
память, диск, задержку, состояние здоровья и статус
|
||
(`Pages/ServersPage.xaml`: `CpuText`, `MemoryText`, `DiskText`,
|
||
`LatencyText`, `HealthText`, `Status`). Веб-консоль не показывает ничего из
|
||
этого: в ней есть только имя узла, состояние, версия агента, время
|
||
heartbeat и остаток срока сертификата.
|
||
|
||
Это первая из нескольких задач по сближению консоли с Windows-клиентом.
|
||
Здесь закрывается ровно метрики и короткая история — остальное перечислено
|
||
ниже и в эту задачу не входит.
|
||
|
||
## Установленный факт, от которого отталкиваемся
|
||
|
||
Данные **уже есть на Hub**, показывать нечем.
|
||
|
||
`ControlStore` содержит таблицу (`ControlStore.cs:81`):
|
||
|
||
```sql
|
||
CREATE TABLE IF NOT EXISTS metric_samples (
|
||
sequence INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
node_id TEXT NOT NULL REFERENCES agents(node_id) ON DELETE CASCADE,
|
||
recorded_at TEXT NOT NULL,
|
||
payload_json TEXT NOT NULL
|
||
);
|
||
CREATE INDEX IF NOT EXISTS ix_metric_samples_node_time
|
||
ON metric_samples(node_id, recorded_at DESC);
|
||
```
|
||
|
||
Наполняется она из heartbeat агента, чистится по `MetricRetentionHours`
|
||
(по умолчанию 168 часов). При этом в группе `/api/v1/control` **нет ни
|
||
одного маршрута для метрик** — я перечитал все `control.Map*` в
|
||
`Program.cs`. То есть оператор физически не может их получить.
|
||
|
||
## Что нужно сделать
|
||
|
||
1. **Добавить в Control чтение метрик под ролью Operator.** Как минимум
|
||
последний срез по каждому узлу и история по одному узлу за period.
|
||
Форму запроса, имена полей и ограничение на объём выбираешь сам и
|
||
обосновываешь в отчёте. Обязательные требования: маршрут в группе
|
||
`control` (то есть `RequireAuthorization("Operator")`), ограничение
|
||
количества возвращаемых точек, и никакого доступа к чужим данным по
|
||
роли Agent или Automation.
|
||
2. **Показать это в консоли** в разделе узлов: текущие CPU, память, диск и
|
||
задержка рядом с узлом, плюс короткая история — так же, как её
|
||
показывает Windows-клиент.
|
||
3. **`payload_json` — данные из внешнего источника.** Он приходит от
|
||
агента. Разбирать его в консоли только через уже имеющийся
|
||
`escapeHtml`, как это сделано с payload событий; ни одной вставки в
|
||
`innerHTML` без экранирования. Отсутствующие или битые поля не должны
|
||
ронять таблицу узлов.
|
||
|
||
## Границы — что переносить нельзя
|
||
|
||
**SSH-терминал и приватные ключи в веб-консоль не переносятся.** Это не
|
||
вопрос трудоёмкости, а заявленное свойство продукта: README обещает
|
||
«opens direct SSH terminals without sending a private terminal key to the
|
||
Hub», а ключ мониторинга и сертификат оператора защищены DPAPI и лежат
|
||
только на Windows-машине. Страница Sessions остаётся у Windows-клиента.
|
||
|
||
Также не входит в эту задачу и делается отдельно: страница Settings,
|
||
группы и теги серверов, alert rules и журнал уведомлений (последние два
|
||
пункта в `docs/roadmap.md` числятся невыполненными и для Windows-клиента).
|
||
|
||
Не трогать: `deploy/**`, релизные workflow, Desktop, схему существующих
|
||
таблиц (добавление индексов допустимо и обосновывается).
|
||
|
||
## Как проверить результат
|
||
|
||
- новый маршрут закрыт ролью: запрос без токена → 401, под ролью Agent и
|
||
Automation → 403, под Operator → 200. Три теста, вывод в отчёт;
|
||
- ограничение объёма истории проверено тестом: запрос заведомо большего
|
||
количества точек возвращает не больше предела;
|
||
- битый или неполный `payload_json` не роняет ни маршрут, ни отрисовку —
|
||
тест на каждую сторону;
|
||
- `dotnet test` целиком зелёный, с выводом;
|
||
- прогоны CI на PR — ссылками.
|
||
|
||
## Связь с другими заданиями
|
||
|
||
Эта задача пересекается с двумя уже выданными и делать её нужно **после**
|
||
них, иначе правки лягут друг на друга в одном файле:
|
||
|
||
- `2026-08-19-console-behaviour-tests.md` — поведенческие тесты консоли.
|
||
Новая функциональность обязана прийти с такими тестами сразу, а не
|
||
проверками строк в HTML;
|
||
- `2026-08-19-console-events-throttle.md` — троттлинг обновления дашборда.
|
||
Метрики увеличат объём каждого обновления, поэтому без троттлинга
|
||
усиление нагрузки станет заметнее.
|
||
|
||
Если считаешь, что порядок должен быть другим, — скажи в отчёте и обоснуй,
|
||
это решение приму.
|
||
|
||
## Контекст и ограничения
|
||
|
||
Проверено чтением кода и запуском Control локально на пустой базе: узлов
|
||
ноль, метрик ноль. Как выглядят настоящие `payload_json` от живого агента,
|
||
я не видел — на живом Hub не проверял. Прежде чем фиксировать контракт
|
||
ответа, посмотри фактическую форму payload в коде агента, а не в моём
|
||
описании.
|