fix: исправлены критические ошибки JavaScript
- Исправлена ошибка 'obj is not defined' в WebSocket onopen - Упрощена логика обработки WebSocket сообщений (убрано дублирование) - Исправлен вызов addSectionToggleHandlers в buildTabs - WebSocket теперь работает в реальном времени с follow=True - Убрана избыточная логика проверки дублирования строк Изменения в WebSocket: - Добавлен потоковый режим с follow=True для локальных контейнеров - Улучшена обработка ошибок - Убрано автоматическое закрытие соединения Изменения в JavaScript: - Исправлена ошибка с неопределенной переменной obj - Упрощена обработка WebSocket сообщений - Улучшена стабильность работы Автор: Сергей Антропов Сайт: https://devops.org.ru
This commit is contained in:
parent
c5c0a6cfe3
commit
18466d2cb0
@ -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))
|
await ws.send_text('\n'.join(logs))
|
||||||
else:
|
else:
|
||||||
await ws.send_text("No logs available for remote container")
|
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:
|
except Exception as e:
|
||||||
await ws.send_text(f"ERROR: cannot get remote logs - {e}")
|
await ws.send_text(f"ERROR: cannot get remote logs - {e}")
|
||||||
return
|
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}")
|
await ws.send_text(f"Connected to container: {container.name}")
|
||||||
|
|
||||||
# Получаем логи (только последние строки, без follow)
|
# Отправляем начальные логи
|
||||||
try:
|
try:
|
||||||
websocket_logger.info(f"Getting logs for container {container.name} (ID: {container.id[:12]})")
|
websocket_logger.info(f"Getting logs for container {container.name} (ID: {container.id[:12]})")
|
||||||
logs = container.logs(tail=tail).decode(errors="ignore")
|
initial_logs = container.logs(tail=tail).decode(errors="ignore")
|
||||||
if logs:
|
if initial_logs:
|
||||||
await ws.send_text(logs)
|
await ws.send_text(initial_logs)
|
||||||
else:
|
else:
|
||||||
await ws.send_text("No logs available")
|
await ws.send_text("No logs available")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
websocket_logger.error(f"Error getting logs for {container.name}: {e}")
|
websocket_logger.error(f"Error getting initial logs for {container.name}: {e}")
|
||||||
await ws.send_text(f"ERROR getting logs: {e}")
|
await ws.send_text(f"ERROR getting initial logs: {e}")
|
||||||
|
|
||||||
# Простое WebSocket соединение - только отправляем логи один раз
|
# Устанавливаем потоковое соединение для получения новых логов
|
||||||
websocket_logger.info(f"WebSocket connection established for {container.name}")
|
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:
|
except WebSocketDisconnect:
|
||||||
websocket_logger.info(f"WebSocket client disconnected")
|
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}")
|
await ws.send_text(f"ERROR: {e}")
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
finally:
|
|
||||||
try:
|
|
||||||
websocket_logger.info(f"Closing WebSocket connection")
|
|
||||||
await ws.close()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
@router.websocket("/fan/{service_name}")
|
@router.websocket("/fan/{service_name}")
|
||||||
async def ws_fan(ws: WebSocket, service_name: str, tail: int = DEFAULT_TAIL, token: Optional[str] = None,
|
async def ws_fan(ws: WebSocket, service_name: str, tail: int = DEFAULT_TAIL, token: Optional[str] = None,
|
||||||
|
@ -1253,7 +1253,7 @@ ${svc.last_modified ? `Обновлено: ${new Date(svc.last_modified * 1000).
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Добавляем обработчики для сворачивания секций после построения интерфейса
|
// Добавляем обработчики для сворачивания секций после построения интерфейса
|
||||||
addSectionToggleHandlers();
|
// Вызов перемещен в конец инициализации
|
||||||
}
|
}
|
||||||
|
|
||||||
function setLayout(cls){
|
function setLayout(cls){
|
||||||
@ -2708,7 +2708,8 @@ function openWs(svc, panel){
|
|||||||
els.logContent.innerHTML = '';
|
els.logContent.innerHTML = '';
|
||||||
}
|
}
|
||||||
// Также очищаем legacy элемент лога
|
// Также очищаем legacy элемент лога
|
||||||
if (obj.logEl) {
|
const obj = state.open[id];
|
||||||
|
if (obj && obj.logEl) {
|
||||||
obj.logEl.innerHTML = '';
|
obj.logEl.innerHTML = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2752,46 +2753,15 @@ function openWs(svc, panel){
|
|||||||
console.log('🚨 Single View WebSocket: Полные данные:', ev.data);
|
console.log('🚨 Single View WebSocket: Полные данные:', ev.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем на дублирование строк и убираем дубликаты
|
// Обрабатываем строки логов
|
||||||
const lines = ev.data.split(/\r?\n/).filter(line => line.trim().length > 0);
|
for (let i=0;i<parts.length;i++){
|
||||||
const uniqueLines = [...new Set(lines)];
|
if (parts[i].length===0 && i===parts.length-1) continue;
|
||||||
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));
|
|
||||||
|
|
||||||
// Используем только уникальные строки
|
// harvest instance ids if present
|
||||||
const uniqueParts = uniqueLines.map(line => line.trim()).filter(line => line.length > 0);
|
const pr = parsePrefixAndStrip(parts[i]);
|
||||||
|
if (pr){ if (!(pr.id8 in inst.filters)) { inst.filters[pr.id8] = true; updateIdFiltersBar(); } }
|
||||||
for (let i=0;i<uniqueParts.length;i++){
|
console.log(`openWs: Calling handleLine for container ${id}, line: "${parts[i].substring(0, 50)}..."`);
|
||||||
// Проверяем каждую часть на FoundINFO:
|
handleLine(id, parts[i]);
|
||||||
if (uniqueParts[i].includes('FoundINFO:')) {
|
|
||||||
console.log('🚨 Single View WebSocket: Часть с FoundINFO:', uniqueParts[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// harvest instance ids if present
|
|
||||||
const pr = parsePrefixAndStrip(uniqueParts[i]);
|
|
||||||
if (pr){ if (!(pr.id8 in inst.filters)) { inst.filters[pr.id8] = true; updateIdFiltersBar(); } }
|
|
||||||
console.log(`openWs: Calling handleLine for container ${id}, line: "${uniqueParts[i].substring(0, 50)}..."`);
|
|
||||||
handleLine(id, uniqueParts[i]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Если дублирования нет, обрабатываем как обычно
|
|
||||||
for (let i=0;i<parts.length;i++){
|
|
||||||
if (parts[i].length===0 && i===parts.length-1) continue;
|
|
||||||
|
|
||||||
// Проверяем каждую часть на FoundINFO:
|
|
||||||
if (parts[i].includes('FoundINFO:')) {
|
|
||||||
console.log('🚨 Single View WebSocket: Часть с FoundINFO:', parts[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// harvest instance ids if present
|
|
||||||
const pr = parsePrefixAndStrip(parts[i]);
|
|
||||||
if (pr){ if (!(pr.id8 in inst.filters)) { inst.filters[pr.id8] = true; updateIdFiltersBar(); } }
|
|
||||||
console.log(`openWs: Calling handleLine for container ${id}, line: "${parts[i].substring(0, 50)}..."`);
|
|
||||||
handleLine(id, parts[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обновляем счетчики после обработки всех строк
|
// Обновляем счетчики после обработки всех строк
|
||||||
|
Loading…
x
Reference in New Issue
Block a user