server-monitor-manager/agents/antigravity/inbox/2026-08-20-console-node-metrics.md
Ochenstarik 7fac6d5d22 chore(agents): задание Antigravity по метрикам узлов в консоли
Windows-клиент показывает CPU, память, диск, задержку и здоровье по
каждому серверу, веб-консоль не показывает ничего из этого. Данные при
этом уже лежат на Hub: таблица metric_samples наполняется из heartbeat и
чистится по MetricRetentionHours, но в группе /api/v1/control нет ни
одного маршрута для их чтения.

Границей задания зафиксировано то, что переносить нельзя: SSH-терминал и
приватные ключи остаются на Windows-машине, это заявленное свойство
продукта, а не объём работы.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 17:38:52 +07:00

110 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Метрики и короткая история узлов в веб-консоли
- **Кому:** `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 в коде агента, а не в моём
описании.