Документация Дашборды

Дашборды

Дашборды позволяют собирать собственные страницы мониторинга из
готовых виджетов: счётчики трафика моков, статистика тест-кейсов, аномалии фаззинга,
статусы хаос-экспериментов, последняя активность аудита и многое другое. Каждый дашборд
— это свободная 12-колоночная сетка: перетаскивайте, меняйте размер и закрепляйте
виджеты, пока страница не покажет ровно то, что нужно вашей команде.

Пользовательский дашборд с несколькими виджетами

Об URL в примерах: во всех примерах используется localhost:5770 — адрес Mockarty по умолчанию. Если ваш экземпляр работает на удалённом сервере, замените localhost:5770 на его реальный адрес (например, https://mockarty.company.com). Подробнее — в Полезных функциях и советах.

Где найти

Откройте Дашборды в боковом меню или перейдите на /ui/widget-dashboards.
Клик по дашборду открывает его по адресу /ui/widget-dashboards/<id>. Старый
адрес /ui/dashboards перенаправляет сюда.

Пустой namespace предлагает стартовый дашборд в один клик — готовый обзор
(трафик, протоколы, error-rate тест-ранов, топ моков, последняя активность),
который дальше настраивается под команду.

Дашборды привязаны к namespace: каждый дашборд принадлежит одному namespace, а
переключатель namespace вверху страницы меняет, какие дашборды вы видите.

Пока загружается пространство или дашборд, прежние карточки скрыты. Если список
не загрузился, страница показывает Не удалось загрузить дашборды и кнопку
Повторить. Это ошибка загрузки, а не признак удаления ваших дашбордов.
Если не загрузился каталог в окне Добавить виджет, окно остаётся открытым
и тоже предлагает Повторить.

При первом открытии новый namespace получает редактируемые стартовые панели,
в том числе Развёртывания. На ней видны прогоны развёртываний по текущим
состояниям за последние 30 дней, число прогонов, требующих внимания, доступные
раннеры и состояние доставки вебхуков. В счётчик требующих внимания входят и
давно не разрешённые прогоны и откаты, которые ещё не удалось подтвердить
проверкой. Источники данных по развёртываниям доступны
только на панелях своего namespace; общая панель не объединяет эти данные
между пространствами.

В стартовый набор входит и панель Deploys — операторский взгляд на журнал
развёртываний, который ведёт пайплайн автономного кодера: исходы за период
(успех / провал / откат), длительность p50 и p95 и последние развёртывания
с исходом каждого прогона. Как и «Развёртывания», эти источники работают
только внутри своего namespace.

Журнал развёртываний фиксирует деплои автономного кодера. Если этого модуля
нет в лицензии, виджеты Deploys скрываются из пикера, а стартовая панель
создаётся без них.

Кто что может

Действие Кто
Просмотр дашбордов и данных виджетов Любой участник namespace
Создание / редактирование / удаление дашбордов и виджетов Owner namespace, либо глобальный admin / support
Создание / редактирование / удаление общих (глобальных) дашбордов Только системный admin / support

Пользователь с ролью viewer в namespace может открывать и читать все дашборды в нём,
но любая попытка что-то изменить отклоняется с кодом 403.

Создание дашборда

  1. Откройте /ui/widget-dashboards и нажмите New dashboard.
  2. Введите имя (обязательно, до 200 символов, уникально в пределах namespace) и при
    необходимости описание.
  3. Пустой дашборд откроется в режиме редактирования — добавьте первый виджет.

Существующий дашборд можно дублировать: копия получает новое имя, которое вы
указываете, и переносит все виджеты вместе с настройками и раскладкой.

Общие (глобальные) дашборды

Обычный дашборд показывает данные одного namespace. Общий дашборд
агрегирует данные по всем namespace инстанса — картина по всей компании:
суммарный трафик моков, тест-кейсы по приоритетам, аномалии фаззинга по
серьёзности, весь парк runner’ов.

Как это работает:

  • Общий дашборд живёт в namespace по умолчанию (sandbox) — его может открыть
    каждый пользователь, поэтому дашборд виден всем. На вкладке такого дашборда —
    иконка глобуса, а в тулбаре — бейдж Все пространства.
  • Создавать и изменять общий дашборд может только системный admin или
    support. Для остальных он доступен только на чтение: элементы
    редактирования скрыты, а прямые API-записи отвечают 403.
  • Чтобы создать общий дашборд, откройте New dashboard в namespace по
    умолчанию и отметьте Общий дашборд (по всем пространствам) — чекбокс
    виден только админам и саппорту. Через API передайте "scope": "global" в
    теле запроса создания; вне namespace по умолчанию запрос отклоняется с 400.
  • Поскольку общий дашборд видят все, на нём доступны только безопасные для
    приватности источники данных
    — агрегаты без имён ресурсов, идентификаторов,
    e-mail, названий пространств и произвольных меток. Пикер виджетов скрывает
    несовместимые источники, а API отклоняет их с 400. В каталоге у каждого
    источника есть флаг globalSafe. Уже существующий общий виджет с таким
    источником показывает ошибку недоступности данных, пока вы не замените его.
    Формула на общем дашборде может использовать только операнды, которые тоже
    разрешены для общих дашбордов; старая формула с несовместимым операндом
    показывает ошибку недоступности данных.

Существующие дашборды не затрагиваются: всё созданное раньше остаётся в рамках
своего namespace.

# Создать общий дашборд (токен admin/support, namespace по умолчанию)
curl -X POST -H "X-API-Key: $TOKEN" -H "Content-Type: application/json" \
  -d '{"name": "Обзор по компании", "scope": "global"}' \
  "http://localhost:5770/api/v1/widget-dashboards?namespace=sandbox"

Добавление виджетов

Нажмите Add widget и выберите источник данных из каталога. Каждый виджет сочетает:

Добавление виджета — выбор источника данных

  • источник данных — что показывать (фиксируется при создании виджета);
  • тип виджета — как отрисовать;
  • необязательные параметры — например, окно времени или количество записей.

Типы виджетов

Тип Отображается как
stat Крупное число
chart_line Линейный график (временной ряд)
chart_area График с заливкой (временной ряд)
chart_bar Столбчатая диаграмма (сравнение категорий)
chart_pie Donut / круговая диаграмма распределения
top_list Ранжированный топ-N список
table Таблица
activity Лента активности (последние события)
status Индикатор состояния с коротким текстом
breakdown Число с разбивкой по под-категориям
text Ваша заметка в Markdown (с Mermaid-диаграммами)

Источники данных по категориям

Категория Источник Показывает Параметры
Mocks mock.total_count Общее число моков в namespace —
Mocks mock.active_count Число активных моков на текущий момент —
Mocks mock.undefined_count Запросы, не совпавшие ни с одним моком period_days (0 = за всё время, 1–365)
Mocks mock.requests_total Всего запросов к мокам за окно period_days
Mocks mock.top Самые нагруженные моки period_days, top_n
Mocks mock.unused Активные моки без вызовов N дней (значение = дней простоя) idle_days (1–365), top_n (1–50)
Mocks mock.distinct_called Сколько разных моков получили хотя бы один запрос за окно period_days (1–365)
Mocks mock.by_tag Активные моки по тегам (включая бакет «без тега») top_n (1–50)
Mocks mock.requests_trend Запросы во времени period_days (1–90), bucket (hour / day)
Mocks mock.requests_by_protocol Трафик в разрезе протоколов period_days
Audit audit.activity Последние события аудита (кто что сделал) limit (1–100)
Audit audit.action_breakdown Активность в разрезе типов действий period_days (1–365), top_n (1–50)
Runners runner.status Парк раннеров по статусам (online / offline) —
Test Cases tcm.summary Тест-кейсы по приоритетам —
Test Cases tcm.cases_by_status Тест-кейсы по статусу воркфлоу folder_id, priority, review_status, severity (все опц.)
Test Cases tcm.cases_by_review_status Тест-кейсы по статусу ревью (draft / in review / approved …) folder_id, priority, severity (опц.)
Test Cases tcm.cases_by_priority Тест-кейсы по приоритету folder_id, review_status, severity (опц.)
Test Cases tcm.cases_by_severity Тест-кейсы по серьёзности folder_id, priority, review_status (опц.)
Test Cases tcm.cases_in_review Сколько кейсов сейчас в ревью folder_id, priority, severity (опц.)
Test Cases tcm.review_age_days Средний / максимальный возраст кейсов в ревью (прокси, см. ниже) folder_id, priority, severity (опц.)
Test Cases tcm.cases_by_tag Тест-кейсы по тегам (кейс попадает в бакет каждого своего тега; без тегов — «Untagged») top_n (1–50), folder_id, priority, review_status, severity
Test Cases tcm.cases_by_custom_field Тест-кейсы по значению одного кастом-поля — график «группировка по лейблу» в стиле Allure. Имя поля сравнивается без учёта регистра; если в одном кейсе есть одинаковые имена с разным регистром, учитывается последнее значение. field (обязателен), top_n (1–50), folder_id, priority, review_status, severity
Test Cases tcm.cases_by_author Топ авторов тест-кейсов (по команде) top_n (1–50), folder_id, priority, review_status, severity
Test Cases tcm.runs_by_executor Топ исполнителей прогонов кейсов за период (по команде) top_n (1–50), period_days (1–365)
Test Plans plans.summary Планы, расписания и недавние запуски —
Test Plans testplan.completions_by_user Топ тех, кто прошёл тест-планы за период (по команде) top_n (1–50), period_days (1–365)
Access users.cases_authored Активность по пользователям: создано кейсов за период (по команде) top_n (1–50), period_days (1–365)
API Tester api_tester.summary Счётчики коллекций, тестов и отчётов —
API Tester api_tester.runs_trend Прогоны тест-отчётов во времени (для графиков error-rate и формул) period_days (1–90), bucket (hour / day), status (all/passed/failed)
Fuzzing fuzz.summary Аномалии фаззинга по серьёзности —
Chaos chaos.summary Хаос-эксперименты по статусам —
Chaos chaos.resilience_avg Средняя оценка устойчивости (0–100) по хаос-прогонам за период period_days
AI Agents agent.tokens_total Потреблено LLM-токенов за период period_days (1–365)
AI Agents agent.tokens_by_namespace Потребление токенов по пространствам имён period_days, top_n (1–50)
AI Agents agent.tokens_trend LLM-токены во времени period_days (1–90), bucket (hour / day)
AI Agents agent.users_top Топ пользователей агентов по токенам (по команде) period_days, top_n
AI Agents agent.subagents_top Топ суб-агентов по выполненным задачам period_days, top_n
Автономный кодер coder.mission_cost LLM-токены по миссиям кодера (крупнейшие потребители) period_days (1–365), limit (1–50)
Автономный кодер coder.hours_saved Сэкономленные человеко-часы миссий, завершённых за период (оценка задачи − время до завершения) period_days (1–365), hours_per_point (1–80)
Миссии missions.by_status Автономные миссии по состояниям period_days (1–365), product_id (необязательно)
Миссии missions.needs_attention Миссии, ожидающие человека product_id (необязательно)
Миссии missions.throughput Число завершённых миссий по дню завершения, включая неуспешные и отменённые period_days (1–180), product_id (необязательно)
Миссии missions.success_rate Доля успешных среди завершённых; отменённые не входят в расчёт period_days (1–365), product_id (необязательно)
Миссии missions.spend_by_product Расход токенов миссий по продуктам period_days (1–365), limit (1–50)
Миссии missions.budget_utilisation Использованная доля заданного бюджета токенов миссий product_id (необязательно)
AI Agents agent.tasks_active Задачи агентов, выполняющиеся сейчас —
AI Agents agent.tasks_by_status Задачи агентов по статусам period_days
Mocks mock.users_top Топ авторов моков (по команде) period_days, top_n
Security security.findings_total Аномалии безопасности за период period_days (1–365)
Security security.findings_by_severity Аномалии по критичности period_days
Security security.findings_trend Аномалии во времени period_days (1–90), bucket, severity (all / critical / high / medium / low / info)
Performance perf.campaigns_active Нагрузочные кампании, идущие сейчас —
Performance perf.campaigns_by_status Нагрузочные кампании по статусам period_days
Performance perf.requests_trend Всего перф-запросов выполнено во времени period_days, bucket
Performance perf.failed_requests_trend Неуспешные перф-запросы во времени (в паре с запросами — формула для error-rate) period_days, bucket
Performance perf.apdex_avg Средний APDEX-индекс по прогонам за период period_days
Performance perf.p95_latency_trend Средняя p95-задержка (мс) по бакетам во времени period_days, bucket
Test Runs test_runs.by_status Запуски тестов по статусам period_days
Test Runs test_runs.trend Запуски тестов во времени period_days (1–90), bucket, status (all / completed / failed / running / pending / interrupted)
Webhooks webhook.deliveries_by_status Доставки вебхуков по статусам period_days
Webhooks webhook.deliveries_trend Доставки вебхуков во времени period_days (1–90), bucket, status (all / delivered / failed / dlq / …)
Recorder recorder.sessions_total Сессии рекордера за период period_days
Deploys deploy.outcomes Исходы развёртываний за период: успех / провал / откат / блокировка / отмена / в работе period_days (1–90), environment (опционально)
Deploys deploy.durations Персентили длительности развёртываний (секунды); на карточке — выбранный персентиль period_days (1–90), percentile (p50 / p95), environment (опционально)
Deploys deploy.runs Последние развёртывания с состоянием и длительностью каждого прогона limit (1–50), period_days (1–90), environment (опционально)
Contracts contract.summary Контрактные прогоны по типу отчёта period_days
Access rbac.namespace_users Участники пространства имён по ролям —
Задачи issuetracker.issues_by_status Задачи по статусу воркфлоу —
Задачи issuetracker.issues_by_priority Задачи по приоритету —
Задачи issuetracker.issues_by_assignee Задачи по исполнителю (внутри команды) —
Задачи issuetracker.open_count Открытые (не завершённые) задачи —
Задачи issuetracker.overdue_count Задачи с просроченным дедлайном —
Задачи issuetracker.created_trend Создание задач во времени period_days (1–90), bucket (hour / day)
Мессенджер chat.messages_by_author_kind Сообщения по типу автора (люди / агенты / система) —
Мессенджер chat.messages_by_thread_kind Сообщения по типу треда (обсуждения / личные / каналы) —
Мессенджер chat.threads_total Треды обсуждений (открытые, не в архиве) —
Вики wiki.pages_total Живые страницы вики —
Вики wiki.pages_created_trend Создание страниц вики во времени period_days (1–90), bucket (hour / day)
Вики wiki.edits_trend Правки вики (сохранения) во времени period_days (1–90), bucket (hour / day)
Система system.resources Загрузка CPU / памяти / диска хоста —
Система system.runtime Рантайм серверного процесса (горутины, куча, GC, аптайм) —
Система system.db_pool Соединения, ожидания и время ожидания пула БД на узле, который отдал панель (не сумма по кластеру) —
Formulas formula.custom Ваша собственная метрика, вычисленная из других источников expression, operands
Formulas formula.timeseries Ваш собственный график: формула, вычисляемая по каждому временному бакету над trend-источниками (например, доля ошибок во времени) expression, operands
Прочее static.text Ваша заметка в Markdown (текстовый виджет) —
Прочее static.html Ваш собственный HTML (со скриптами) в песочнице-фрейме —
Прочее static.embed Живая внешняя страница внутри карточки (например, борд Grafana) —

Почасовые и суточные интервалы для прогонов тестов, находок безопасности,
расхода токенов ИИ, отчётов API Tester, доставок вебхуков, запросов и задержки
нагрузочных тестов и завершённых миссий считаются по UTC. Поэтому график
показывает одинаковые интервалы на разных узлах даже при разных часовых
поясах сеансов базы данных.

Параметры проверяются по схеме источника при сохранении — неизвестный параметр или
значение вне диапазона отклоняется с понятным сообщением об ошибке, виджет не
создаётся.

Точный, всегда актуальный каталог (включая схему параметров каждого источника)
доступен через API: GET /api/v1/widget-dashboards/catalog.

Командная аналитика

Помимо «как используется инструмент», дашборды отвечают на управленческие вопросы
о людях и процессах
: кто написал больше всего тест-кейсов, кто прошёл какие
тест-планы, сколько кейсов лежит в ревью и как долго.

  • Источники процесса (tcm.cases_by_review_status, tcm.cases_by_priority,
    tcm.cases_by_severity, tcm.cases_in_review, tcm.review_age_days)
    показывают форму бэклога тест-кейсов через фиксированные метки и счётчики.
    Их можно вынести на общий глобальный дашборд. Названия статусов воркфлоу,
    теги и значения кастом-полей могут содержать данные команды, поэтому их
    разрезы доступны только в одном пространстве.
  • Источники по людям (tcm.cases_by_author, tcm.runs_by_executor,
    testplan.completions_by_user, users.cases_authored) привязывают работу к
    конкретному участнику. Поскольку они раскрывают личность человека, они
    доступны только в рамках команды: вы видите участников своей команды и никогда —
    людей из другой команды; на глобальный дашборд их добавить нельзя.

Все источники процесса и людей принимают опциональные фильтры — можно сузить до одной
папки, приоритета, статуса ревью или серьёзности: выберите значение при добавлении
виджета, и он пересчитается только по подходящим кейсам. Ещё два фильтра по
косвенным признакам — как в Allure: tag (только кейсы с этим тегом) и cf
(только кейсы с кастом-полем, в формате key=value, например component=cart).
Их можно комбинировать — например, «кейсы по приоритету, tag=regression,
cf=team=payments» — чтобы нарезать любую разбивку под реальный процесс команды.

Возраст ревью — это прокси. tcm.review_age_days оценивает, сколько кейсы лежат в
ревью, измеряя время с момента последнего редактирования (сейчас − последнее
изменение). Активно редактируемый кейс показывает меньший возраст; залежавшийся —
реальный возраст бэклога. Виджет честно помечает это как прокси — Mockarty пока не
хранит отдельную метку «переведён в ревью».

Формулы — свои метрики

Источник «Своя формула» (категория Формулы) позволяет построить метрику,
которой нет в каталоге «из коробки», — комбинируя другие источники обычной
арифметикой. Без языка запросов: вы задаёте до 5 операндов (буквы A–E),
привязываете каждый к источнику данных и пишете выражение вида A / B * 100.

В пикере «Добавить виджет» выберите «Своя формула» — вместо обычной формы
параметров появится конструктор формулы:

Добавление виджета — конструктор формулы

  • Операнды — по строке на букву. Каждая строка выбирает источник данных (любой
    источник, отдающий число или распределение; формула не может ссылаться на другую
    формулу). Для источников-распределений дополнительно выбирается метрика:
    «Сумма (total)» или «Элемент по имени…» — один именованный срез, имя
    сравнивается без учёта регистра (например, failed). Если у источника есть
    параметры (например, period_days), компактная форма параметров появляется прямо
    в строке.
  • Выражение — арифметика над буквами операндов: + - * /, скобки, числа
    (десятичные допустимы), унарный минус. Проверяется на лету при вводе; та же
    проверка выполняется на сервере при сохранении.
  • Отображение — знаки после запятой (Авто / 0–3) и произвольный суффикс
    (например, %) для отображаемого числа.

Результат — одно число, поэтому подходят типы виджетов Stat и Status,
включая пороги (например, подсветить карточку красным, когда доля ошибок превысит 5).

Пример — stat «процент упавших запусков тестов»:

  1. Операнд A: источник Запуски тестов по статусам, метрика «Элемент по
    имени…»
    → failed.
  2. Операнд B: источник Запуски тестов по статусам, метрика «Сумма (total)».
  3. Выражение: A / B * 100, суффикс %, один знак после запятой.

Деление на ноль и отсутствующее имя элемента отображаются как ошибка только внутри
этого виджета — остальной дашборд продолжает работать.

Добавить виджет-формулу через API

curl -X POST -H "X-API-Key: $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "title": "Failed runs %",
    "widgetType": "stat",
    "dataSourceId": "formula.custom",
    "paramsJson": {
      "expression": "A / B * 100",
      "operands": [
        {"ref": "A", "sourceId": "test_runs.by_status", "select": "item:failed"},
        {"ref": "B", "sourceId": "test_runs.by_status", "select": "total"}
      ]
    },
    "vizOptionsJson": {"decimals": 1, "suffix": "%"},
    "gridW": 3, "gridH": 3
  }' \
  "http://localhost:5770/api/v1/widget-dashboards/<dashboardId>/widgets?namespace=default"

select — это "total" (по умолчанию) или "item:<имя>" для
источников-распределений; числовым источникам select не нужен. Некорректное
выражение, неизвестный источник операнда или буква в выражении без строки операнда
отклоняются с точным сообщением об ошибке.

Свои графики — формула во времени

Источник «Свой график (формула во времени)» (formula.timeseries) — тот же
конструктор, но каждый операнд привязывается к trend-источнику («…во времени»),
а выражение вычисляется для каждого временного бакета — результатом будет ряд,
который рисуют типы виджетов Line и Area.

Конструктор начинается с готовых рецептов — шаблонов в один клик для частых
формул (% ошибок тест-ранов, успешность вебхуков, доля critical-аномалий). Выберите
рецепт и подстройте — или соберите с нуля:

  1. Задайте ось времени — одно окно (дней) и бакет (hour / day) на всю
    формулу. Все операнды используют эту ось, поэтому ряды всегда выровнены.
  2. Операнд A: источник Запуски тестов во времени, параметр status → failed.
  3. Операнд B: источник Запуски тестов во времени, status → all.
  4. Выражение: A / B * 100. Тип виджета: Line.

Бакет, в котором выражение вычислить нельзя (например, деление на ноль в день без
запусков), просто пропускается — на графике будет разрыв, а не фальшивый ноль.

Опции «Отображение» работают и здесь: задайте число знаков и суффикс (например,
%) — ось Y и тултип графика покажут 60.7 % вместо сырого числа. Серия в тултипе
называется по заголовку виджета.

Порог-зоны. Линейные, area- и bar-графики принимают те же пороги, что и
числовые виджеты — и рисуют их цветными зонами: с каждого порога начинается
полупрозрачная полоса с пунктирной границей, так что «выше 5% — плохо» видно с
одного взгляда. Ось Y растягивается так, чтобы самая высокая зона оставалась
видимой, даже если данные до неё ещё не дошли. Пороги задаются в настройках
виджета или через API (vizOptionsJson.thresholds, например
[{"value": 5, "color": "yellow"}, {"value": 10, "color": "red"}]).

Текст и заметки — Markdown-виджеты

Источник «Текст / заметка» (категория Прочее) добавляет на дашборд карточку с
произвольным текстом: фрагмент ранбука, контакты дежурных, легенда к соседним
метрикам, ссылки на документацию. Это единственный виджет, который не запрашивает
данных — содержимое вы пишете сами.

Выберите «Текст / заметка» в окне добавления виджета — на шаге настройки вместо
параметров появится редактор «Содержимое (Markdown)». Поддерживается стандартный
Markdown:

  • заголовки, абзацы, жирный / курсив;
  • маркированные и нумерованные списки, таблицы, цитаты;
  • встроенный код и блоки кода;
  • ссылки и изображения.

Сырой HTML вычищается при отображении — скрипты, фреймы и обработчики событий никогда
не рендерятся, поэтому текстовый виджет безопасно размещать и на общем (глобальном)
дашборде.

Свой HTML и живые встраивания

Рядом с «Текст / заметка» (категория Прочее) живут ещё два авторских виджета:

Свой HTML (static.html) рендерит написанный вами HTML — включая скрипты —
внутри песочницы-iframe на карточке. Скрипты могут ходить в API самого приложения
с вашей сессией (fetch('/api/v1/…', {credentials: 'include'})), тянуть данные
откуда угодно и рисовать результат как угодно. Дашборд становится полностью
программируемым: агент (или вы) генерирует нужную визуализацию одним
HTML-сниппетом и кладёт её на борд. Карточка растягивается как любой виджет,
размер сохраняется. Лимит контента: 16 КБ. Поскольку HTML выполняется с сессией зрителя,
авторинг ограничен: создавать и редактировать Custom HTML-виджет может только
владелец пространства (или системный admin / support) — это проверяет сервер.
Модель повторяет admin-only HTML-панели Grafana.

Встраивание / iframe (static.embed) показывает живую внешнюю страницу внутри
карточки: борд Grafana, статус-страницу, любой дашборд, доступный из браузера
зрителя. Укажите URL — целевой сайт должен разрешать встраивание (не отдавать
X-Frame-Options: DENY / ограничивающий frame-ancestors). Авторизация —
браузерная: войдите на встраиваемый сайт в этом же браузере, и его cookie
действуют внутри фрейма (для cross-site конфигураций целевой сайт должен выдавать
сессионную cookie с SameSite=None; Secure). Подсказка для Grafana: добавьте
?kiosk, чтобы скрыть её интерфейс, и включите allow_embedding = true в
grafana.ini.

Диаграммы Mermaid

Блок кода с языком mermaid рендерится как диаграмма прямо на карточке — блок-схемы,
диаграммы последовательностей, машины состояний:

# Процесс релиза

```mermaid
graph LR
  Build --> Test --> Deploy
```

Диаграммы автоматически следуют светлой/тёмной теме. Если в диаграмме синтаксическая
ошибка, на её месте появится аккуратная заметка об ошибке — остальная карточка
продолжит отображаться.

Чтобы изменить текст позже, откройте настройки виджета (иконка шестерёнки) — появится
тот же редактор с текущим содержимым.

Добавить текстовый виджет через API

Содержимое передаётся в vizOptionsJson.markdown (до 16 КБ); paramsJson для этого
источника остаётся пустым:

curl -X POST -H "X-API-Key: $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "title": "Ранбук команды",
    "widgetType": "text",
    "dataSourceId": "static.text",
    "vizOptionsJson": {"markdown": "# Дежурство\n\n- Сначала смотрим виджет error-rate\n\n```mermaid\ngraph LR\n  Alert --> Triage --> Fix\n```"},
    "gridW": 4, "gridH": 4
  }' \
  "http://localhost:5770/api/v1/widget-dashboards/<dashboardId>/widgets?namespace=default"

Раскладка: перетаскивание, размер, закрепление

Сетка состоит из 12 колонок. В режиме редактирования:

  • Перетаскивайте виджет за заголовок; соседние виджеты автоматически
    раздвигаются.
  • Меняйте размер за правый нижний угол. У каждого виджета есть минимальный размер.
  • Закрепляйте виджет, чтобы другие виджеты не сдвигали его при перетаскивании.

Раскладка сохраняется автоматически после сессии перетаскивания/изменения размера и
переживает обновление страницы для всех участников namespace.

Живые обновления

Открытый дашборд обновляется сам — нажимать Обновить не нужно. Маленькая
точка рядом с кнопкой Обновить показывает состояние соединения:

  • Зелёная, пульсирует — живые обновления активны. Дашборд проверяет
    новые значения виджетов и перерисовывает их при изменении.
  • Серая — соединение прервалось, страница переподключается; восстановление
    происходит само за несколько секунд.

После изменения тест-кейсов связанные показатели дашборда обновляются и в
том случае, если кейс изменили через другой admin-узел Mockarty. Небольшая
задержка при доставке изменения до дашборда нормальна.

Пока вы редактируете раскладку, живые перерисовки придерживаются, чтобы сетка
не двигалась под курсором; свежие данные появятся сразу после сохранения или
отмены редактирования.

Селект интервала автообновления в тулбаре остаётся как резервный режим
опроса (например, если корпоративный прокси блокирует потоковые соединения).
Когда живые обновления работают, правильный выбор — оставить его Выкл.

Экспорт и печать

Откройте меню ⋮ дашборда (справа в тулбаре), чтобы поделиться дашбордом за
пределами Mockarty:

  • Экспорт HTML — скачивает один полностью автономный .html-файл: дашборд
    ровно таким, каким вы его видите (сетка, карточки, графики как статичные
    изображения), без внешних ресурсов — открывается где угодно, в том числе в
    закрытом контуре и как вложение в письме. Файл несёт машиночитаемые атрибуты
    (data-widget-id, data-widget-type, data-source-id, data-params,
    data-grid на каждой карточке; data-value на числовых значениях), так что
    скрипты и BI-инструменты разбирают снапшот без скрейпинга картинки.
  • Экспорт JSON — скачивает конфигурацию дашборда плюс свежевычисленные
    данные виджетов с сервера: {dashboard, widgets, data}. Каждый виджет несёт
    type, dataSourceId, params, позицию grid и thresholds; data
    содержит те же послотовые данные, что и живой рендер.
  • Экспорт CSV — скачивает плоскую таблицу метрик для Excel / Google Sheets /
    BI-инструментов: widget_id, widget_title, widget_type, data_source_id, metric, value, по строке на значение (круговая диаграмма даёт строку на
    сегмент, временной ряд — строку на точку). Файл начинается с UTF-8 BOM, чтобы
    Excel корректно определил кодировку.
  • Экспорт конфигурации — скачивает только конфигурацию дашборда (без
    данных, без внутренних идентификаторов, без пространства имён) как переносимый
    JSON-файл. Используйте его, чтобы передать дашборд другой команде — см.
    следующий раздел.
  • Импортировать дашборд — создаёт новый дашборд из такого файла
    конфигурации. Доступен и на пустом состоянии, когда в пространстве имён ещё нет
    дашбордов.
  • Печать / PDF — открывает диалог печати браузера. Выберите Сохранить как
    PDF
    . Интерфейс приложения (сайдбар, вкладки, тулбар) скрывается
    автоматически; сетка виджетов печатается в светлой палитре, каждая карточка
    остаётся на одной странице.

Экспорт JSON и CSV вычисляется на сервере, поэтому отражает актуальные данные, а
не кеш браузера. Каждый экспорт фиксируется в журнале аудита.

Перенос дашборда между командами

Если одна команда собрала удачный дашборд, экспортируйте его конфигурацию и
передайте файл — принимающая команда импортирует его в своё пространство имён, и виджеты
посчитаются уже по их данным:

  1. На исходном дашборде откройте меню ⋮ → Экспорт конфигурации. Вы
    получите файл <имя>-config.json, содержащий только имя дашборда, описание и
    конфигурацию виджетов (тип, источник данных, параметры, пороги, раскладку
    сетки). Ничего специфичного для пространства имён в файл не попадает.
  2. Принимающая команда открывает Пользовательские дашборды в своём
    пространстве имён и выбирает меню ⋮ → Импортировать дашборд (или «Импортировать
    дашборд» на пустом состоянии), затем указывает файл. Новый дашборд появится и
    станет активным.

Правила импорта:

  • Для импорта нужны права на запись (владелец пространства имён, администратор или
    поддержка).
  • Файл проверяется строго: типы виджетов и источники данных должны существовать
    на принимающем сервере, параметры виджетов перепроверяются по схеме каждого
    источника. Неизвестные источники перечисляются в сообщении об ошибке.
  • Если дашборд с таким именем уже существует, импорт получит имя
    <имя> (imported) (затем <имя> (imported 2) и так далее).
  • Ограничения в 30 виджетов и 200 символов действуют и для импорта.

Ограничения

  • 30 виджетов на дашборд — добавление 31-го отклоняется, в том числе когда несколько пользователей добавляют виджеты одновременно.
  • Если старый дашборд уже содержит более 30 виджетов, запросы дашборда, данных и экспорта возвращают HTTP 409. Попросите администратора исправить сохранённую конфигурацию; сервер не скрывает часть виджетов.
  • Имена дашбордов и заголовки виджетов: до 200 символов.
  • Данные виджетов кратковременно кешируются на сервере (от нескольких секунд до
    нескольких минут в зависимости от источника), поэтому даже загруженный дашборд с
    множеством зрителей остаётся дешёвым.
  • Если один источник данных упал, ошибку показывает только его виджет — остальной
    дашборд отрисовывается нормально.

Примеры API

Все эндпоинты живут под /api/v1/widget-dashboards. Namespace передаётся в query-параметре
?namespace= (по умолчанию default). Аутентификация — API-токен в заголовке
X-API-Key.

Список дашбордов

curl -H "X-API-Key: $TOKEN" \
  "http://localhost:5770/api/v1/widget-dashboards?namespace=default"

Создать дашборд

curl -X POST -H "X-API-Key: $TOKEN" -H "Content-Type: application/json" \
  -d '{"name": "Обзор QA-команды", "description": "Моки + здоровье тестов"}' \
  "http://localhost:5770/api/v1/widget-dashboards?namespace=default"

Посмотреть каталог источников данных

curl -H "X-API-Key: $TOKEN" \
  "http://localhost:5770/api/v1/widget-dashboards/catalog"

Добавить виджет

curl -X POST -H "X-API-Key: $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "title": "Запросы во времени",
    "widgetType": "chart_line",
    "dataSourceId": "mock.requests_trend",
    "paramsJson": {"period_days": 7, "bucket": "day"},
    "gridX": 0, "gridY": 0, "gridW": 6, "gridH": 4
  }' \
  "http://localhost:5770/api/v1/widget-dashboards/<dashboardId>/widgets?namespace=default"

Получить дашборд с его виджетами

curl -H "X-API-Key: $TOKEN" \
  "http://localhost:5770/api/v1/widget-dashboards/<dashboardId>?namespace=default"

Получить «живые» данные виджетов

curl -H "X-API-Key: $TOKEN" \
  "http://localhost:5770/api/v1/widget-dashboards/<dashboardId>/data?namespace=default"

Каждый элемент в ответе несёт либо data (вычисленное значение), либо error
(почему именно этот виджет не смог посчитаться) — упавший источник никогда не ломает
весь ответ.

Когда узел занят вычислением других дашбордов, /data возвращает HTTP 429 с
Retry-After: 1. Повторяйте запрос после этого интервала, без множества
параллельных попыток. В кластере лимит действует отдельно на каждом узле.

Поток живых данных виджетов (SSE)

curl -N -H "X-API-Key: $TOKEN" \
  "http://localhost:5770/api/v1/widget-dashboards/<dashboardId>/stream?namespace=default"

Сервер держит соединение открытым и присылает фрейм event: widgets с тем же
форматом items, что и эндпоинт /data, — но только когда значения
действительно изменились. Между изменениями соединение поддерживают
комментарии-heartbeat’ы. Веб-интерфейс использует этот поток для живых
обновлений; его можно потреблять и из скриптов или внешних дашбордов.
Когда вычислительные ресурсы заняты, поток сохраняет последний фрейм и
повторяет попытку при следующем обновлении; неизменившийся фрейм не отправляется.

Экспорт дашборда (JSON / CSV)

# Конфигурация + свежевычисленные данные как JSON
curl -OJ -H "X-API-Key: $TOKEN" \
  "http://localhost:5770/api/v1/widget-dashboards/<dashboardId>/export?namespace=default&format=json"

# Плоская таблица метрик для Excel / BI-инструментов
curl -OJ -H "X-API-Key: $TOKEN" \
  "http://localhost:5770/api/v1/widget-dashboards/<dashboardId>/export?namespace=default&format=csv"

-OJ сохраняет файл под именем, которое предлагает сервер
(<имя-дашборда>-<дата>.json / .csv).
Экспорт JSON и CSV может вернуть HTTP 429 с Retry-After: 1, когда вычисление
данных занято. Экспорт одной конфигурации не вычисляет данные виджетов и
остаётся доступен.

Перенести дашборд другой команде (экспорт конфигурации + импорт)

# 1. Экспортировать переносимую конфигурацию (без данных, ids и пространства имён)
curl -OJ -H "X-API-Key: $TOKEN" \
  "http://localhost:5770/api/v1/widget-dashboards/<dashboardId>/export?namespace=team-a&format=config"

# 2. Импортировать её в другое пространство имён (файл из шага 1 как тело запроса)
curl -X POST -H "X-API-Key: $TOKEN" -H "Content-Type: application/json" \
  --data @overview-config.json \
  "http://localhost:5770/api/v1/widget-dashboards/import?namespace=team-b"

Импорт отвечает 201 с созданным дашбордом. 400 перечисляет ровно то, что
принимающий сервер не принял (например, неизвестные источники данных).

Изменить имя / описание дашборда

curl -X PATCH -H "X-API-Key: $TOKEN" -H "Content-Type: application/json" \
  -d '{"name": "Обзор QA-команды v2"}' \
  "http://localhost:5770/api/v1/widget-dashboards/<dashboardId>?namespace=default"

Изменить виджет

curl -X PATCH -H "X-API-Key: $TOKEN" -H "Content-Type: application/json" \
  -d '{"title": "Трафик моков (14д)", "paramsJson": {"period_days": 14}}' \
  "http://localhost:5770/api/v1/widget-dashboards/<dashboardId>/widgets/<widgetId>?namespace=default"

Массово сохранить раскладку

curl -X PUT -H "X-API-Key: $TOKEN" -H "Content-Type: application/json" \
  -d '{"items": [{"id": "<widgetId>", "gridX": 6, "gridY": 0, "gridW": 6, "gridH": 4}]}' \
  "http://localhost:5770/api/v1/widget-dashboards/<dashboardId>/layout?namespace=default"

Дублировать дашборд

curl -X POST -H "X-API-Key: $TOKEN" -H "Content-Type: application/json" \
  -d '{"name": "Обзор QA-команды (копия)"}' \
  "http://localhost:5770/api/v1/widget-dashboards/<dashboardId>/duplicate?namespace=default"

Удалить виджет / дашборд

curl -X DELETE -H "X-API-Key: $TOKEN" \
  "http://localhost:5770/api/v1/widget-dashboards/<dashboardId>/widgets/<widgetId>?namespace=default"

curl -X DELETE -H "X-API-Key: $TOKEN" \
  "http://localhost:5770/api/v1/widget-dashboards/<dashboardId>?namespace=default"

После удаления дашборда чтение по его id отвечает 404.