From ea62f1082957c02125d979f9d865338382804ca6 Mon Sep 17 00:00:00 2001 From: jze9 Date: Fri, 28 Aug 2026 17:00:19 +0500 Subject: [PATCH] =?UTF-8?q?feat(admin):=20=D1=81=D0=BE=D1=81=D1=82=D0=BE?= =?UTF-8?q?=D1=8F=D0=BD=D0=B8=D0=B5=20=D0=B8=D0=BD=D1=84=D1=80=D0=B0=D1=81?= =?UTF-8?q?=D1=82=D1=80=D1=83=D0=BA=D1=82=D1=83=D1=80=D1=8B=20=D0=BD=D0=B0?= =?UTF-8?q?=20=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B8=D1=86=D0=B5=20=D0=BE?= =?UTF-8?q?=D1=82=D0=BB=D0=B0=D0=B4=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Сегодняшняя авария (упал гипервизор — вместе с ним брокер, Ollama, прокси) проявлялась в отладке косвенно: пустой список воркеров и ошибка очередей. Прямого ответа «что именно недоступно» страница не давала, хотя эндпоинт /admin/health его уже знает. Блок статусов рисуется и тогда, когда сам срез не собрался — именно в аварии он нужен больше всего, а собирается в этот момент дольше обычного. Co-Authored-By: Claude Opus 5 --- docs/ARCHITECTURE.md | 5 +- services/frontend/src/pages/admin/Debug.tsx | 52 ++++++++++++++++++--- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index f1be38e..bdc98c4 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -221,7 +221,10 @@ Identity (Universal Auth) и генерирует `.env` заново (`infisica Кнопки «Запустить всё» / «Остановить всё» — массовый старт и кооперативная отмена (флаг `cancel_requested`, воркер останавливается сам на ближайшем тике; уже начатый прогон не рвём посреди записи в базу). -- **Панель отладки** (админка → «Отладка», `GET /api/admin/debug`): один срез — +- **Панель отладки** (админка → «Отладка», `GET /api/admin/debug` + `/health`): + один срез — доступность инфраструктуры (PostgreSQL/Redis/MinIO/ES/Ollama/ + брокер: этот блок показывается даже когда сам срез не собирается, потому что + при аварии первый вопрос — что именно отвалилось), живые воркеры Celery и что именно они крутят, глубина очередей RabbitMQ (в т.ч. `unacked` и число потребителей), покрытие корпуса эмбеддингами, активные и проблемные прогоны, зависшие прогоны (нет heartbeat >10 мин), diff --git a/services/frontend/src/pages/admin/Debug.tsx b/services/frontend/src/pages/admin/Debug.tsx index 321b38d..2a4789c 100644 --- a/services/frontend/src/pages/admin/Debug.tsx +++ b/services/frontend/src/pages/admin/Debug.tsx @@ -1,11 +1,13 @@ import React from 'react'; import { useQuery } from '@tanstack/react-query'; import { - Activity, AlertTriangle, Cpu, Database, Layers, RefreshCw, Settings2, ListTree, + Activity, AlertTriangle, CheckCircle2, Cpu, Database, Layers, RefreshCw, + Server, Settings2, ListTree, XCircle, } from 'lucide-react'; import { adminApi } from '../../api/client'; import { ProgressBar } from '../../components/ProgressBar'; +interface Health { name: string; ok: boolean; detail?: string } interface ActiveTask { name: string; id: string; args: string; started_ago_s: number | null } interface Worker { name: string; concurrency: number | null; reserved: number; active: ActiveTask[] } interface Run { @@ -56,12 +58,23 @@ export function Debug() { queryFn: () => adminApi.debug().then((r) => r.data as DebugData), refetchInterval: 5000, }); + // Отдельным запросом: когда отваливается инфраструктура (брокер, Ollama), + // отладка должна первой показывать ЧТО именно недоступно, а не только следствия + const { data: health } = useQuery({ + queryKey: ['admin-health'], + queryFn: () => adminApi.health().then((r) => r.data as Health[]), + refetchInterval: 10000, + }); - if (error) { - return
Не удалось получить срез состояния: {String(error)}
; - } - if (!data) { - return
Сбор данных…
; + if (error || !data) { + return ( +
+ {error + ?
Не удалось получить срез состояния: {String(error)}
+ :
Сбор данных…
} + +
+ ); } const queuesErr = 'error' in data.queues ? (data.queues as { error: string }).error : null; @@ -80,6 +93,8 @@ export function Debug() { срез от {new Date(data.generated_at).toLocaleTimeString('ru-RU')} + + {/* Активные прогоны заливки */} {data.sources.stale_run_ids.length > 0 && ( @@ -244,6 +259,31 @@ export function Debug() { ); } +/** Что из инфраструктуры доступно прямо сейчас — первый вопрос при разборе аварии. */ +function HealthCard({ health }: { health?: Health[] }) { + return ( + + {health?.length ? ( +
+ {health.map((h) => ( +
+ + {h.ok + ? + : } + {h.name} + + + {h.detail || (h.ok ? 'OK' : 'недоступен')} + +
+ ))} +
+ ) :

Опрос сервисов…

} +
+ ); +} + function Card({ icon: Icon, title, children }: { icon: React.ElementType; title: string; children: React.ReactNode }) { return (