/** * System Health Panel Component * * Real-time system monitoring dashboard showing: * - CPU usage * - Memory usage * - Disk usage * - Database health * - Recent activity metrics */ import React, { useState, useEffect, useCallback } from 'react'; import { Activity, Cpu, HardDrive, Database, Server, RefreshCw, CheckCircle, AlertTriangle, XCircle, Wifi, Clock, Users, Zap, TrendingUp, BarChart3 } from 'lucide-react'; import { getToken } from '../../services/api'; const API_BASE = import.meta.env.VITE_API_URL || ''; // Status indicator component const StatusIndicator = ({ status }) => { const getStatusConfig = () => { switch (status) { case 'healthy': case 'connected': return { icon: CheckCircle, color: '#10b981', label: 'Healthy' }; case 'warning': case 'degraded': return { icon: AlertTriangle, color: '#f59e0b', label: 'Warning' }; case 'critical': case 'error': case 'disconnected': return { icon: XCircle, color: '#ef4444', label: 'Critical' }; default: return { icon: Activity, color: '#6b7280', label: 'Unknown' }; } }; const { icon: Icon, color, label } = getStatusConfig(); return (
{label}
); }; // Metric Card Component const MetricCard = ({ icon: Icon, title, value, unit, percentage, status, description }) => { const getBarColor = (pct) => { if (pct < 60) return '#10b981'; if (pct < 80) return '#f59e0b'; return '#ef4444'; }; return (

{title}

{value} {unit && {unit}}
{percentage !== undefined && (
)} {description &&

{description}

}
); }; // Realtime Stats Row const RealtimeStats = ({ metrics }) => { if (!metrics) return null; return (
{metrics.requests_per_hour || 0} Requests/hr
{metrics.errors_per_hour || 0} Errors/hr
{metrics.active_users || 0} Active Users
); }; function SystemHealthPanel() { const [health, setHealth] = useState(null); const [realtime, setRealtime] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [lastUpdate, setLastUpdate] = useState(null); const [autoRefresh, setAutoRefresh] = useState(true); // Fetch full health data const fetchHealth = useCallback(async () => { setLoading(true); setError(null); try { const token = getToken(); const response = await fetch(`${API_BASE}/api/admin/health`, { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }); if (!response.ok) throw new Error('Failed to fetch health data'); const data = await response.json(); if (data.success) { setHealth(data.health); setLastUpdate(new Date()); } } catch (err) { setError(err.message); } finally { setLoading(false); } }, []); // Fetch lightweight realtime metrics const fetchRealtime = useCallback(async () => { try { const token = getToken(); const response = await fetch(`${API_BASE}/api/admin/health/realtime`, { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }); if (response.ok) { const data = await response.json(); if (data.success) { setRealtime(data.metrics); setLastUpdate(new Date()); } } } catch (err) { console.error('Realtime fetch error:', err); } }, []); // Initial fetch useEffect(() => { fetchHealth(); }, [fetchHealth]); // Auto-refresh realtime metrics every 5 seconds useEffect(() => { if (!autoRefresh) return; const interval = setInterval(fetchRealtime, 5000); return () => clearInterval(interval); }, [autoRefresh, fetchRealtime]); if (loading) { return (

Loading system health...

); } if (error) { return (

Error: {error}

); } const cpu = health?.cpu || {}; const memory = health?.memory || {}; const disk = health?.disk || {}; const database = health?.database || {}; const overallStatus = realtime?.overall_status || health?.overall_status || 'unknown'; return (
{/* Header */}

System Health

{lastUpdate && ( {lastUpdate.toLocaleTimeString()} )}
{/* Realtime Stats */} {/* Metric Cards */}
{/* Database Stats */} {database.table_stats && (

Database Tables

{Object.entries(database.table_stats).map(([table, count]) => (
{table} {count.toLocaleString()} rows
))}
)} {/* Process Info */} {health?.process && (

Process Info

Process Memory {health.process.memory_mb?.toFixed(1)} MB
CPU Usage {health.process.cpu_percent?.toFixed(1)}%
Threads {health.process.threads}
Open Files {health.process.open_files}
)}
); } export default SystemHealthPanel;