diff --git a/app/api/v1/endpoints/websocket.py b/app/api/v1/endpoints/websocket.py index a4056b1..2682b69 100644 --- a/app/api/v1/endpoints/websocket.py +++ b/app/api/v1/endpoints/websocket.py @@ -96,6 +96,11 @@ async def ws_logs(ws: WebSocket, container_id: str, tail: int = DEFAULT_TAIL, to await ws.send_text('\n'.join(logs)) else: await ws.send_text("No logs available for remote container") + + # Для удаленных контейнеров пока просто отправляем начальные логи + # TODO: Реализовать мониторинг файлов логов в реальном времени + websocket_logger.info(f"Remote WebSocket connection established for {container_name} on {hostname}") + except Exception as e: await ws.send_text(f"ERROR: cannot get remote logs - {e}") return @@ -119,20 +124,38 @@ async def ws_logs(ws: WebSocket, container_id: str, tail: int = DEFAULT_TAIL, to # Отправляем начальное сообщение await ws.send_text(f"Connected to container: {container.name}") - # Получаем логи (только последние строки, без follow) + # Отправляем начальные логи try: websocket_logger.info(f"Getting logs for container {container.name} (ID: {container.id[:12]})") - logs = container.logs(tail=tail).decode(errors="ignore") - if logs: - await ws.send_text(logs) + initial_logs = container.logs(tail=tail).decode(errors="ignore") + if initial_logs: + await ws.send_text(initial_logs) else: await ws.send_text("No logs available") except Exception as e: - websocket_logger.error(f"Error getting logs for {container.name}: {e}") - await ws.send_text(f"ERROR getting logs: {e}") + websocket_logger.error(f"Error getting initial logs for {container.name}: {e}") + await ws.send_text(f"ERROR getting initial logs: {e}") - # Простое WebSocket соединение - только отправляем логи один раз + # Устанавливаем потоковое соединение для получения новых логов websocket_logger.info(f"WebSocket connection established for {container.name}") + + try: + # Получаем логи в реальном времени с follow=True + stream = container.logs(stream=True, follow=True, tail=0) + for chunk in stream: + if chunk is None: + break + try: + await ws.send_text(chunk.decode(errors="ignore")) + except WebSocketDisconnect: + stream.close() + return + except Exception as e: + websocket_logger.error(f"Error streaming logs for {container.name}: {e}") + break + stream.close() + except Exception as e: + websocket_logger.error(f"Error setting up log stream for {container.name}: {e}") except WebSocketDisconnect: websocket_logger.info(f"WebSocket client disconnected") @@ -142,12 +165,6 @@ async def ws_logs(ws: WebSocket, container_id: str, tail: int = DEFAULT_TAIL, to await ws.send_text(f"ERROR: {e}") except: pass - finally: - try: - websocket_logger.info(f"Closing WebSocket connection") - await ws.close() - except: - pass @router.websocket("/fan/{service_name}") async def ws_fan(ws: WebSocket, service_name: str, tail: int = DEFAULT_TAIL, token: Optional[str] = None, diff --git a/app/static/js/index.js b/app/static/js/index.js index 36e2500..d369ddc 100644 --- a/app/static/js/index.js +++ b/app/static/js/index.js @@ -1253,7 +1253,7 @@ ${svc.last_modified ? `Обновлено: ${new Date(svc.last_modified * 1000). } // Добавляем обработчики для сворачивания секций после построения интерфейса - addSectionToggleHandlers(); + // Вызов перемещен в конец инициализации } function setLayout(cls){ @@ -2708,7 +2708,8 @@ function openWs(svc, panel){ els.logContent.innerHTML = ''; } // Также очищаем legacy элемент лога - if (obj.logEl) { + const obj = state.open[id]; + if (obj && obj.logEl) { obj.logEl.innerHTML = ''; } @@ -2752,46 +2753,15 @@ function openWs(svc, panel){ console.log('🚨 Single View WebSocket: Полные данные:', ev.data); } - // Проверяем на дублирование строк и убираем дубликаты - const lines = ev.data.split(/\r?\n/).filter(line => line.trim().length > 0); - const uniqueLines = [...new Set(lines)]; - if (lines.length !== uniqueLines.length) { - console.log('🚨 Single View WebSocket: ОБНАРУЖЕНО ДУБЛИРОВАНИЕ строк!'); - console.log('🚨 Single View WebSocket: Всего строк:', lines.length); - console.log('🚨 Single View WebSocket: Уникальных строк:', uniqueLines.length); - console.log('🚨 Single View WebSocket: Дублированные строки:', lines.filter((line, index) => lines.indexOf(line) !== index)); + // Обрабатываем строки логов + for (let i=0;i line.trim()).filter(line => line.length > 0); - - for (let i=0;i