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
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>