Skip to content

Канал обратной связи (Feedback FAB + RUM)

Обновлено: 17.05.2026 Статус: wave K-FB1 live с 13.05. Floating Feedback Button виден на каждой странице AntRoute. Backend feedback_reports + rum_events принимает submission'ы; первый реальный feedback от Андрея получен 16.05 13:36. Адресат: Андрей (главный pilot tester), технолог-заказчик, диспетчер — все, кто видит несоответствия в продукте и хочет их зафиксировать без выхода в почту/Telegram.

Описывает канал обратной связи AntRoute: глобальный FAB-виджет на каждой странице (text/voice/screenshot), RUM-телеметрия (JS errors / UX metrics), как админ читает поток.

1. Зачем это нужно

Андрей и пилотные пользователи находят расхождения «инструкция — реальный интерфейс» в реальном времени. Email / Telegram теряют контекст: какая страница, какой role, какой timestamp. Feedback FAB решает это:

  • кнопка на каждой странице, доступна одним кликом;
  • автоматически фиксирует URL, role, timestamp, viewport, browser;
  • сохраняет screenshot + audio + текст (опционально);
  • доступен и анонимно (anti-bot токен публичный), и под auth;
  • backend хранит в feedback_reports, новые записи доступны админу через Django shell или будущий admin UI.

Параллельно RUM (rum_events) собирает performance + UX-метрики: route_change, long_task (>50ms), inp, lcp, fcp, cls, nav_timing, click_latency — для последующего поиска hotspot'ов.

2. FAB-виджет

Кнопка живёт в правом нижнем углу любой страницы. На скриншоте — кнопка свёрнута, видна как небольшой floating button:

FAB closed — visible bottom-right

Клик открывает modal с тремя секциями: текст, voice, screenshot:

FAB open — feedback modal

Что в модальном диалоге:

  • Текст — opional, multi-line input для описания проблемы;
  • Voice — кнопка записи (MediaRecorder API), запись отправляется как audio blob, backend транскрибирует через Yandex SpeechKit (Mail.ru-Business credentials в .env);
  • Screenshot — кнопка «Сделать скриншот» использует html2canvas библиотеку, захватывает текущую страницу;
  • Submit — кнопка отправки; вызывает useFeedback.submitFeedback() который:
    1. ждёт window.__antrouteRumFlush() (≤800 мс) — чтобы RUM breadcrumbs дошли до Feedback,
    2. берёт anti-bot токен через GET /anti-bot/token/,
    3. POST /feedback/report/ с multipart form (text + audio_blob + screenshot_blob + metadata);
  • Anonymous OK — если пользователь не залогинен, submit идёт без Authorization header (anti-bot токен публичный по дизайну).

3. RUM телеметрия

В отличие от FAB (явный click пользователя), RUM пассивный — собирает performance-метрики автоматически. Регистрируется в App.tsx через useEffect один раз на mount, использует PerformanceObserver + sendBeacon.

Что собирается:

МетрикаТипSource
route_changenavigation eventReact Router navigation listener
long_task> 50ms main-thread blocksPerformanceObserver longtask entries
inpinput delayInteraction-to-Next-Paint Web Vital
lcpLargest Contentful PaintWeb Vital
fcpFirst Contentful PaintWeb Vital
clsCumulative Layout ShiftWeb Vital
nav_timingserver response timingsPerformanceNavigationTiming
click_latencyclick → next paintmanual measurement

Особенность: user_id в rum_events всегда NULL — RUM-клиент по дизайну не пробрасывает user_id, только session_id. Это privacy-by-design choice.

4. Что админ видит сейчас

4.1. Полу-автоматический monitor

Скрипт scripts/feedback-monitor.sh (см. K-FB1 §Block 4) polling'ом раз в 20 сек проверяет feedback_reports и rum_events, при новой строке шлёт сигнал в tmux antroute_claude — Claude видит баг и фиксит за 15-20 мин. Реализация ситуативная, пока без admin UI.

4.2. SQL queries

Прямой доступ к таблицам через postgres docker:

sql
-- последние feedback за сутки
SELECT id, status, feedback_type, page_url, created_at
FROM feedback_reports
WHERE created_at > NOW() - INTERVAL '24 hours'
ORDER BY created_at DESC;

-- топ-URL по RUM events
SELECT url, count(*) FROM rum_events
WHERE created_at > NOW() - INTERVAL '24 hours'
GROUP BY url ORDER BY count(*) DESC LIMIT 20;

-- /login long_tasks performance check
SELECT count(*) FROM rum_events
WHERE metric = 'long_task' AND url = '/login'
  AND created_at > NOW() - INTERVAL '24 hours';

4.3. Пример живого feedback

Первый реальный feedback от Андрея (id=5, 16.05 13:36):

text
Page: /technology/operations/5db76ac4-7f0e-464e-aaf7-fc70df6c4888
Title: Технологическая операция — AntRoute
Type: bug
Browser: Chrome 148 on Windows
Screenshot: 83 KB attached

Message:
«Отсутствует подраздел "Операции" левой боковой панели раздела
Технология. В breadcrumbs он есть /Технология/Операции/ ... А в
панели его нет. Непорядок :)»

Из этого admin узнал:

  • Sidebar (/components/layout/Sidebar.tsx:136) не содержит /technology/operations;
  • Breadcrumb labels (/components/common/Breadcrumbs.tsx:44) показывают «Операции» → расхождение.

Это материал для следующего fix-wave'а.

5. Маршрут просмотра на 5 минут

  1. Войти под любым пользователем (например, koc-4505016987-admin).
  2. Открыть любую /v/... страницу.
  3. Увидеть FAB в правом нижнем углу.
  4. Кликнуть → открыть modal.
  5. (Опционально) записать короткое голосовое сообщение.
  6. (Опционально) сделать скриншот.
  7. Ввести текст «test feedback».
  8. Submit → toast «Отправлено».
  9. Открыть Django shell на сервере: python manage.py shell -c "from feedback.models import FeedbackReport; print(FeedbackReport.objects.last())" — увидеть свою запись.

6. Что отложено

  • Admin UI — пока чтение feedback через SQL / Django shell. Web-интерфейс для админа («Inbox feedback с фильтрами, threads, replies, status workflow») — отдельная задача.
  • Notifications об ответе — пользователь отправил feedback, не знает что с ним. Email-уведомления «Ваш feedback принят / fixed» — будущая задача.
  • Mobile FAB — Flutter mobile приложение пока не имеет FAB. Отдельный wave.
  • Audio transcription readback — backend транскрибирует Voice через Yandex SpeechKit, но текст транскрипта не отдаётся обратно пользователю для проверки.
  • Screenshot annotations — пользователь не может рисовать поверх скриншота (стрелки, обводки). Только raw capture.

7. Что искать в обратной связи о самом feedback'е

(Мета-фидбек: фидбек о канале фидбека.)

  1. FAB видимость. Заметна ли кнопка, или сливается с UI? Должна ли она быть более яркой или вызывающей?
  2. Modal flow. Удобно ли «текст + voice + screenshot» как три секции, или нужно «one-click submit text-only»?
  3. Anonymous OK. Является ли возможность отправлять без логина важной (например, для технологов-заказчиков с временным доступом)?
  4. Acknowledgment. Достаточно ли toast'а «Отправлено», или нужно явное «#5 принято, рассмотрим в течение N дней»?
  5. Permission model. Должен ли feedback модератор иметь возможность видеть screenshot/audio до текста (security review) или сразу всё?

8. Дисциплина обновления

  • При появлении admin UI для чтения feedback — добавить раздел §4.3 с скриншотом интерфейса.
  • При расширении набора RUM метрик — обновить §3 таблицу.
  • При появлении mobile FAB — добавить §9 о mobile.

Приложение. Evidence в репозитории

  • docs/sprint_2026_may/active/K-FB1-feedback-fab-rum.md — task file со списком блоков (Block 1 backend done, Block 2-5 файл устарел — по факту FAB live с 13.05).
  • antroute_backend/feedback/ — Django app (models, serializers, views, services, tests).
  • antroute_backend/monitoring/ — Django app для RUM events.
  • frontend/src/components/common/FeedbackFab.tsx — FAB виджет.
  • frontend/src/hooks/useFeedback.ts — логика записи / submit.
  • frontend/src/utils/rumClient.ts — RUM client.
  • Yandex SpeechKit credentials — YANDEX_API_KEY + YANDEX_FOLDER_ID в .env (Mail.ru-Business).
  • feedback_monitor_runbook.md — runbook armming / отключения agent-side Monitor'ов (см. memory reference_k_fb1_monitor_runbook.md).

AntRoute MES — управление блуждающими узкими местами