UNPKG

claude-flow-novice

Version:

Claude Flow Novice - Advanced orchestration platform for multi-agent AI workflows with CFN Loop architecture Includes Local RuVector Accelerator and all CFN skills for complete functionality.

671 lines (585 loc) 25.9 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CFN Docker Monitoring Dashboard</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: linear-gradient(135deg, #1e3c72, #2a5298); color: #fff; min-height: 100vh; padding: 20px; } .dashboard { max-width: 1400px; margin: 0 auto; } .header { text-align: center; margin-bottom: 30px; } .header h1 { font-size: 2.5em; margin-bottom: 10px; text-shadow: 2px 2px 4px rgba(0,0,0,0.3); } .status-bar { background: rgba(255,255,255,0.1); padding: 15px; border-radius: 10px; margin-bottom: 20px; backdrop-filter: blur(10px); display: flex; justify-content: space-between; align-items: center; } .status-indicator { display: flex; align-items: center; gap: 10px; } .status-dot { width: 12px; height: 12px; border-radius: 50%; animation: pulse 2s infinite; } .status-dot.online { background: #4ade80; } .status-dot.offline { background: #f87171; } .status-dot.warning { background: #fbbf24; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-bottom: 30px; } .card { background: rgba(255,255,255,0.1); border-radius: 15px; padding: 20px; backdrop-filter: blur(10px); border: 1px solid rgba(255,255,255,0.2); transition: transform 0.3s ease, box-shadow 0.3s ease; } .card:hover { transform: translateY(-5px); box-shadow: 0 10px 25px rgba(0,0,0,0.2); } .card h3 { margin-bottom: 15px; font-size: 1.3em; color: #4ade80; } .metric { display: flex; justify-content: space-between; margin-bottom: 10px; padding: 8px 0; border-bottom: 1px solid rgba(255,255,255,0.1); } .metric:last-child { border-bottom: none; } .metric-value { font-weight: bold; color: #4ade80; } .metric-value.warning { color: #fbbf24; } .metric-value.critical { color: #f87171; } .progress-bar { width: 100%; height: 8px; background: rgba(255,255,255,0.2); border-radius: 4px; overflow: hidden; margin-top: 5px; } .progress-fill { height: 100%; background: linear-gradient(90deg, #4ade80, #22c55e); transition: width 0.5s ease; } .progress-fill.warning { background: linear-gradient(90deg, #fbbf24, #f59e0b); } .progress-fill.critical { background: linear-gradient(90deg, #f87171, #ef4444); } .container-list { max-height: 400px; overflow-y: auto; } .container-item { background: rgba(255,255,255,0.05); border-radius: 8px; padding: 15px; margin-bottom: 10px; display: flex; justify-content: space-between; align-items: center; } .container-name { font-weight: bold; margin-bottom: 5px; } .container-status { display: flex; align-items: center; gap: 10px; } .logs-container { background: #1a1a1a; border-radius: 10px; padding: 20px; font-family: 'Courier New', monospace; font-size: 14px; max-height: 300px; overflow-y: auto; } .log-entry { margin-bottom: 5px; padding: 2px 0; } .log-entry.error { color: #f87171; } .log-entry.warning { color: #fbbf24; } .log-entry.info { color: #60a5fa; } .log-entry.success { color: #4ade80; } .refresh-btn { background: linear-gradient(135deg, #4ade80, #22c55e); border: none; color: white; padding: 10px 20px; border-radius: 5px; cursor: pointer; font-weight: bold; transition: all 0.3s ease; } .refresh-btn:hover { transform: translateY(-2px); box-shadow: 0 5px 15px rgba(74, 222, 128, 0.3); } .alert { background: rgba(248, 113, 113, 0.2); border: 1px solid #f87171; border-radius: 8px; padding: 15px; margin-bottom: 20px; display: none; } .alert.show { display: block; } </style> </head> <body> <div class="dashboard"> <div class="header"> <h1>🐳 CFN Docker Monitoring Dashboard</h1> <p>Real-time monitoring for CFN container infrastructure</p> </div> <div class="status-bar"> <div class="status-indicator"> <div class="status-dot" id="system-status"></div> <span id="system-status-text">Checking...</span> </div> <div> <span id="last-update">Last updated: Never</span> <button class="refresh-btn" onclick="refreshData()">Refresh</button> </div> </div> <div class="alert" id="alert-container"> <strong>🚨 Alert:</strong> <span id="alert-message"></span> </div> <div class="grid"> <div class="card"> <h3>📊 System Overview</h3> <div class="metric"> <span>Total Containers</span> <span class="metric-value" id="total-containers">-</span> </div> <div class="metric"> <span>Running Containers</span> <span class="metric-value" id="running-containers">-</span> </div> <div class="metric"> <span>Failed Containers</span> <span class="metric-value" id="failed-containers">-</span> </div> <div class="metric"> <span>System Load</span> <span class="metric-value" id="system-load">-</span> </div> </div> <div class="card"> <h3>💾 Memory Usage</h3> <div class="metric"> <span>Total Memory</span> <span class="metric-value" id="total-memory">-</span> </div> <div class="metric"> <span>Used Memory</span> <span class="metric-value" id="used-memory">-</span> </div> <div class="metric"> <span>Memory Usage</span> <span class="metric-value" id="memory-percent">-</span> </div> <div class="progress-bar"> <div class="progress-fill" id="memory-progress" style="width: 0%"></div> </div> </div> <div class="card"> <h3>🔄 CFN Loop Status</h3> <div class="metric"> <span>Active Tasks</span> <span class="metric-value" id="active-tasks">-</span> </div> <div class="metric"> <span>Completed Tasks</span> <span class="metric-value" id="completed-tasks">-</span> </div> <div class="metric"> <span>Failed Tasks</span> <span class="metric-value" id="failed-tasks">-</span> </div> <div class="metric"> <span>Avg Confidence</span> <span class="metric-value" id="avg-confidence">-</span> </div> </div> <div class="card"> <h3>🚨 Agent Health</h3> <div class="metric"> <span>Healthy Agents</span> <span class="metric-value" id="healthy-agents">-</span> </div> <div class="metric"> <span>Stuck Agents</span> <span class="metric-value" id="stuck-agents">-</span> </div> <div class="metric"> <span>Memory Alerts</span> <span class="metric-value" id="memory-alerts">-</span> </div> <div class="metric"> <span>Timeout Rate</span> <span class="metric-value" id="timeout-rate">-</span> </div> </div> <div class="card"> <h3>📊 CFN Agents (SQLite)</h3> <div class="metric"> <span>Total Agents</span> <span class="metric-value" id="sqlite-total-agents">-</span> </div> <div class="metric"> <span>Active Agents</span> <span class="metric-value" id="sqlite-active-agents">-</span> </div> <div class="metric"> <span>Completed Agents</span> <span class="metric-value" id="sqlite-completed-agents">-</span> </div> <div class="metric"> <span>Failed Agents</span> <span class="metric-value" id="sqlite-failed-agents">-</span> </div> </div> <div class="card"> <h3>📡 Redis Swarm Signals</h3> <div class="metric"> <span>Active Signals</span> <span class="metric-value" id="redis-signals-count">-</span> </div> <div class="metric"> <span>Latest Signal</span> <span class="metric-value" id="redis-latest-signal" style="font-size: 0.8em;">-</span> </div> <div class="metric"> <span>Redis Status</span> <span class="metric-value" id="redis-status">-</span> </div> <div class="metric"> <span>Last Signal Time</span> <span class="metric-value" id="redis-last-signal-time">-</span> </div> </div> </div> <div class="grid"> <div class="card"> <h3>🐳 Container Status</h3> <div class="container-list" id="container-list"> <div class="container-item"> <span>Loading containers...</span> </div> </div> </div> <div class="card"> <h3>📋 Recent Logs</h3> <div class="logs-container" id="logs-container"> <div class="log-entry info">Dashboard initialized...</div> </div> </div> </div> </div> <script> let alertCount = 0; async function fetchContainerStats() { try { const response = await fetch('/api/containers'); return await response.json(); } catch (error) { console.error('Failed to fetch container stats:', error); return null; } } async function fetchSystemStats() { try { const response = await fetch('/api/system'); return await response.json(); } catch (error) { console.error('Failed to fetch system stats:', error); return null; } } async function fetchCFNStats() { try { const response = await fetch('/api/cfn'); return await response.json(); } catch (error) { console.error('Failed to fetch CFN stats:', error); return null; } } async function fetchSQLiteAgents() { try { const response = await fetch('/api/agents'); if (!response.ok) { throw new Error('Failed to fetch agents data'); } const data = await response.json(); return data; } catch (error) { console.error('Failed to fetch SQLite agents:', error); return null; } } async function fetchRedisSignals() { try { const response = await fetch('/api/redis/signals'); if (!response.ok) { throw new Error('Failed to fetch Redis signals'); } const data = await response.json(); return data; } catch (error) { console.error('Failed to fetch Redis signals:', error); return null; } } function updateMemoryUsage(used, total) { const percent = Math.round((used / total) * 100); const progressBar = document.getElementById('memory-progress'); const percentText = document.getElementById('memory-percent'); progressBar.style.width = percent + '%'; percentText.textContent = percent + '%'; if (percent > 90) { progressBar.className = 'progress-fill critical'; percentText.className = 'metric-value critical'; showAlert('Critical memory usage: ' + percent + '%'); } else if (percent > 70) { progressBar.className = 'progress-fill warning'; percentText.className = 'metric-value warning'; } else { progressBar.className = 'progress-fill'; percentText.className = 'metric-value'; } } function updateSystemStatus(online) { const statusDot = document.getElementById('system-status'); const statusText = document.getElementById('system-status-text'); if (online) { statusDot.className = 'status-dot online'; statusText.textContent = 'All Systems Online'; } else { statusDot.className = 'status-dot offline'; statusText.textContent = 'System Offline'; } } function showAlert(message) { const alertContainer = document.getElementById('alert-container'); const alertMessage = document.getElementById('alert-message'); alertMessage.textContent = message; alertContainer.className = 'alert show'; setTimeout(() => { alertContainer.className = 'alert'; }, 5000); } function addLog(message, type = 'info') { const logsContainer = document.getElementById('logs-container'); const logEntry = document.createElement('div'); const timestamp = new Date().toLocaleTimeString(); logEntry.className = `log-entry ${type}`; logEntry.textContent = `[${timestamp}] ${message}`; logsContainer.appendChild(logEntry); logsContainer.scrollTop = logsContainer.scrollHeight; if (logsContainer.children.length > 50) { logsContainer.removeChild(logsContainer.firstChild); } } function formatBytes(bytes) { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB', 'TB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } async function refreshData() { addLog('Refreshing dashboard data...', 'info'); try { // Simulate API calls with mock data for demo const containerStats = await fetchContainerStats() || { total: 8, running: 6, failed: 2, containers: [ { name: 'cfn-orchestrator', status: 'running', memory: '2.1GB', cpu: '15%' }, { name: 'cfn-agent-task', status: 'running', memory: '1.8GB', cpu: '25%' }, { name: 'redis-cfn-loop', status: 'running', memory: '256MB', cpu: '2%' }, { name: 'cfn-telemetry', status: 'running', memory: '128MB', cpu: '1%' }, { name: 'cfn-dashboard', status: 'stopped', memory: '0MB', cpu: '0%' }, { name: 'cadvisor-cfn-loop', status: 'running', memory: '45MB', cpu: '3%' } ] }; const systemStats = await fetchSystemStats() || { memoryTotal: 16 * 1024 * 1024 * 1024, memoryUsed: 8.5 * 1024 * 1024 * 1024, load: 2.1 }; const cfnStats = await fetchCFNStats() || { activeTasks: 1, completedTasks: 12, failedTasks: 1, avgConfidence: 0.87, healthyAgents: 5, stuckAgents: 0, memoryAlerts: 0, timeoutRate: '5%' }; // Fetch SQLite agents data const sqliteAgents = await fetchSQLiteAgents(); if (sqliteAgents && sqliteAgents.success) { const agents = sqliteAgents.data; const activeCount = agents.filter(a => a.status === 'active' || a.status === 'in_progress').length; const completedCount = agents.filter(a => a.status === 'completed').length; const failedCount = agents.filter(a => a.status === 'failed').length; document.getElementById('sqlite-total-agents').textContent = agents.length; document.getElementById('sqlite-active-agents').textContent = activeCount; document.getElementById('sqlite-completed-agents').textContent = completedCount; document.getElementById('sqlite-failed-agents').textContent = failedCount; } else { document.getElementById('sqlite-total-agents').textContent = '0'; document.getElementById('sqlite-active-agents').textContent = '0'; document.getElementById('sqlite-completed-agents').textContent = '0'; document.getElementById('sqlite-failed-agents').textContent = '0'; } // Fetch Redis signals const redisSignals = await fetchRedisSignals(); if (redisSignals && redisSignals.success) { const signals = redisSignals.data; document.getElementById('redis-signals-count').textContent = signals.length; document.getElementById('redis-status').textContent = 'Connected'; if (signals.length > 0) { const latestSignal = signals[signals.length - 1]; document.getElementById('redis-latest-signal').textContent = latestSignal.key.replace('swarm:', ''); document.getElementById('redis-last-signal-time').textContent = new Date(latestSignal.timestamp).toLocaleTimeString(); } else { document.getElementById('redis-latest-signal').textContent = 'No signals'; document.getElementById('redis-last-signal-time').textContent = '-'; } } else { document.getElementById('redis-signals-count').textContent = '0'; document.getElementById('redis-status').textContent = 'Disconnected'; document.getElementById('redis-latest-signal').textContent = '-'; document.getElementById('redis-last-signal-time').textContent = '-'; } // Update System Overview document.getElementById('total-containers').textContent = containerStats.total; document.getElementById('running-containers').textContent = containerStats.running; document.getElementById('failed-containers').textContent = containerStats.failed; document.getElementById('system-load').textContent = systemStats.load.toFixed(1); // Update Memory Usage const memoryPercent = Math.round((systemStats.memoryUsed / systemStats.memoryTotal) * 100); document.getElementById('total-memory').textContent = formatBytes(systemStats.memoryTotal); document.getElementById('used-memory').textContent = formatBytes(systemStats.memoryUsed); updateMemoryUsage(systemStats.memoryUsed, systemStats.memoryTotal); // Update CFN Loop Status document.getElementById('active-tasks').textContent = cfnStats.activeTasks; document.getElementById('completed-tasks').textContent = cfnStats.completedTasks; document.getElementById('failed-tasks').textContent = cfnStats.failedTasks; document.getElementById('avg-confidence').textContent = (cfnStats.avgConfidence * 100).toFixed(1) + '%'; // Update Agent Health document.getElementById('healthy-agents').textContent = cfnStats.healthyAgents; document.getElementById('stuck-agents').textContent = cfnStats.stuckAgents; document.getElementById('memory-alerts').textContent = cfnStats.memoryAlerts; document.getElementById('timeout-rate').textContent = cfnStats.timeoutRate; // Update Container List const containerList = document.getElementById('container-list'); containerList.innerHTML = ''; containerStats.containers.forEach(container => { const containerItem = document.createElement('div'); containerItem.className = 'container-item'; const statusClass = container.status === 'running' ? 'online' : container.status === 'exited' ? 'offline' : 'warning'; containerItem.innerHTML = ` <div> <div class="container-name">${container.name}</div> <div>Memory: ${container.memory} | CPU: ${container.cpu}</div> </div> <div class="container-status"> <div class="status-dot ${statusClass}"></div> <span>${container.status}</span> </div> `; containerList.appendChild(containerItem); }); updateSystemStatus(containerStats.running > 0); document.getElementById('last-update').textContent = 'Last updated: ' + new Date().toLocaleTimeString(); addLog('Dashboard updated successfully', 'success'); } catch (error) { console.error('Error refreshing data:', error); addLog('Failed to refresh dashboard data: ' + error.message, 'error'); showAlert('Failed to refresh dashboard data'); } } // Initialize dashboard refreshData(); // Auto-refresh every 10 seconds setInterval(refreshData, 10000); // Add some initial demo logs setTimeout(() => { addLog('CFN Docker monitoring system initialized', 'success'); addLog('Connected to Redis coordination system', 'success'); addLog('Container monitoring active', 'info'); addLog('SQLite agents monitoring enabled', 'info'); addLog('Redis swarm signals monitoring enabled', 'info'); }, 1000); </script> </body> </html>