Spaces:
Paused
Paused
| #!/usr/bin/env python3 | |
| """ | |
| Ultra Simple Production Monitoring Dashboard | |
| Minimal dependencies - uses only standard library | |
| """ | |
| import json | |
| import time | |
| from datetime import datetime | |
| from http.server import BaseHTTPRequestHandler, HTTPServer | |
| try: | |
| import requests # type: ignore | |
| except ImportError: | |
| requests = None # type: ignore | |
| # Simple metrics store | |
| metrics = {"cpu_percent": [], "memory_percent": [], "disk_percent": [], "timestamps": [], "system_info": {}} | |
| class MonitoringDashboardHandler(BaseHTTPRequestHandler): | |
| def do_GET(self): | |
| if self.path == "/": | |
| self.serve_dashboard() | |
| elif self.path == "/api/metrics": | |
| self.serve_metrics() | |
| elif self.path == "/api/health": | |
| self.serve_health() | |
| elif self.path == "/api/environments": | |
| self.serve_environments() | |
| else: | |
| self.send_404() | |
| def serve_dashboard(self): | |
| self.send_response(200) | |
| self.send_header("Content-type", "text/html") | |
| self.end_headers() | |
| html = """ | |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Production Monitoring Dashboard</title> | |
| <style> | |
| * { margin: 0; padding: 0; box-sizing: border-box; } | |
| body { | |
| font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; | |
| background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%); | |
| color: white; min-height: 100vh; | |
| } | |
| .container { max-width: 1200px; margin: 0 auto; padding: 20px; } | |
| .header { text-align: center; margin-bottom: 40px; } | |
| .header h1 { font-size: 2.5rem; margin-bottom: 10px; } | |
| .header p { font-size: 1.1rem; opacity: 0.8; } | |
| .metrics-grid { | |
| display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); | |
| gap: 20px; margin-bottom: 40px; | |
| } | |
| .metric-card { | |
| background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(10px); | |
| border-radius: 15px; padding: 25px; border: 1px solid rgba(255, 255, 255, 0.2); | |
| transition: transform 0.3s ease; | |
| } | |
| .metric-card:hover { transform: translateY(-5px); } | |
| .metric-title { font-size: 1.2rem; margin-bottom: 15px; color: #64b5f6; } | |
| .metric-value { font-size: 2rem; font-weight: bold; margin-bottom: 5px; } | |
| .metric-label { font-size: 0.9rem; opacity: 0.7; } | |
| .env-card { | |
| background: rgba(255, 255, 255, 0.15); backdrop-filter: blur(10px); | |
| border-radius: 15px; padding: 20px; margin-bottom: 20px; | |
| border: 2px solid rgba(255, 255, 255, 0.3); | |
| } | |
| .env-blue { border-color: #4fc3f7; } | |
| .env-green { border-color: #66bb6a; } | |
| .env-status { display: flex; align-items: center; margin-bottom: 10px; } | |
| .env-indicator { width: 16px; height: 16px; border-radius: 50%; margin-right: 10px; } | |
| .status-healthy { background: #4caf50; } | |
| .status-unhealthy { background: #f44336; } | |
| .status-unknown { background: #ff9800; } | |
| .refresh-btn { | |
| background: #64b5f6; color: white; border: none; padding: 10px 20px; | |
| border-radius: 25px; cursor: pointer; font-size: 1rem; | |
| transition: background 0.3s ease; | |
| } | |
| .refresh-btn:hover { background: #42a5f5; } | |
| .last-updated { text-align: center; opacity: 0.7; margin-top: 20px; } | |
| .two-column { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <div class="header"> | |
| <h1>π Production Monitoring Dashboard</h1> | |
| <p>Real-time system and application monitoring</p> | |
| <button class="refresh-btn" onclick="refreshData()">π Refresh Data</button> | |
| </div> | |
| <div class="section-title">π» System Resources</div> | |
| <div class="metrics-grid"> | |
| <div class="metric-card"> | |
| <div class="metric-title">π₯οΈ CPU Usage</div> | |
| <div class="metric-value" id="cpu-value">--%</div> | |
| <div class="metric-label">Processing load</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div class="metric-title">π§ Memory Usage</div> | |
| <div class="metric-value" id="memory-value">--%</div> | |
| <div class="metric-label">Memory consumption</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div class="metric-title">πΎ Disk Usage</div> | |
| <div class="metric-value" id="disk-value">--%</div> | |
| <div class="metric-label">Storage utilization</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div class="metric-title">β±οΈ Uptime</div> | |
| <div class="metric-value" id="uptime-value">--</div> | |
| <div class="metric-label">System running time</div> | |
| </div> | |
| </div> | |
| <div class="section-title">π Deployment Environments</div> | |
| <div class="two-column"> | |
| <div class="env-card env-blue"> | |
| <div style="font-size: 1.3rem; margin-bottom: 15px;">π΅ Blue Environment</div> | |
| <div class="env-status"> | |
| <div id="blue-status-indicator" class="env-indicator status-unknown"></div> | |
| <span id="blue-status-text">Checking...</span> | |
| </div> | |
| <div style="font-size: 1.1rem;" id="blue-response-time">Response Time: --ms</div> | |
| <div style="font-size: 1.1rem;" id="blue-endpoint">Endpoint: http://localhost:5002</div> | |
| </div> | |
| <div class="env-card env-green"> | |
| <div style="font-size: 1.3rem; margin-bottom: 15px;">π’ Green Environment</div> | |
| <div class="env-status"> | |
| <div id="green-status-indicator" class="env-indicator status-unknown"></div> | |
| <span id="green-status-text">Checking...</span> | |
| </div> | |
| <div style="font-size: 1.1rem;" id="green-response-time">Response Time: --ms</div> | |
| <div style="font-size: 1.1rem;" id="green-endpoint">Endpoint: http://localhost:5003</div> | |
| </div> | |
| </div> | |
| <div class="last-updated" id="last-updated"> | |
| Last updated: Loading... | |
| </div> | |
| </div> | |
| <script> | |
| async function fetchEndpoint(endpoint) { | |
| try { | |
| const response = await fetch(endpoint); | |
| return await response.json(); | |
| } catch (error) { | |
| console.error('Error fetching', endpoint, ':', error); | |
| return null; | |
| } | |
| } | |
| function updateDashboard(data) { | |
| if (!data) return; | |
| document.getElementById('cpu-value').textContent = data.cpu_percent?.toFixed(1) + '%' || '--%'; | |
| document.getElementById('memory-value').textContent = data.memory_percent?.toFixed(1) + '%' || '--%'; | |
| document.getElementById('disk-value').textContent = data.disk_percent?.toFixed(1) + '%' || '--%'; | |
| document.getElementById('uptime-value').textContent = data.uptime || '--'; | |
| document.getElementById('last-updated').textContent = | |
| 'Last updated: ' + new Date().toLocaleTimeString(); | |
| } | |
| function updateEnvironments(data) { | |
| if (!data) return; | |
| const blueHealthy = data.blue_environment?.healthy || false; | |
| const blueTime = data.blue_environment?.response_time || 0; | |
| document.getElementById('blue-status-indicator').className = | |
| 'env-indicator ' + (blueHealthy ? 'status-healthy' : 'status-unhealthy'); | |
| document.getElementById('blue-status-text').textContent = | |
| blueHealthy ? 'Healthy' : 'Unhealthy'; | |
| document.getElementById('blue-response-time').textContent = | |
| 'Response Time: ' + blueTime + 'ms'; | |
| const greenHealthy = data.green_environment?.healthy || false; | |
| const greenTime = data.green_environment?.response_time || 0; | |
| document.getElementById('green-status-indicator').className = | |
| 'env-indicator ' + (greenHealthy ? 'status-healthy' : 'status-unhealthy'); | |
| document.getElementById('green-status-text').textContent = | |
| greenHealthy ? 'Healthy' : 'Unhealthy'; | |
| document.getElementById('green-response-time').textContent = | |
| 'Response Time: ' + greenTime + 'ms'; | |
| } | |
| async function refreshData() { | |
| const [metrics, environments] = await Promise.all([ | |
| fetchEndpoint('/api/metrics'), | |
| fetchEndpoint('/api/environments') | |
| ]); | |
| updateDashboard(metrics); | |
| updateEnvironments(environments); | |
| } | |
| setInterval(refreshData, 5000); | |
| refreshData(); | |
| </script> | |
| </body> | |
| </html> | |
| """ | |
| self.wfile.write(html.encode()) | |
| def serve_metrics(self): | |
| self.send_response(200) | |
| self.send_header("Content-type", "application/json") | |
| self.end_headers() | |
| current_metrics = collect_system_metrics() | |
| response = json.dumps(current_metrics, indent=2) | |
| self.wfile.write(response.encode()) | |
| def serve_health(self): | |
| self.send_response(200) | |
| self.send_header("Content-type", "application/json") | |
| self.end_headers() | |
| health_data = { | |
| "status": "healthy", | |
| "timestamp": datetime.now().isoformat(), | |
| "version": "1.0.0", | |
| "uptime": time.time() - start_time, | |
| } | |
| response = json.dumps(health_data, indent=2) | |
| self.wfile.write(response.encode()) | |
| def serve_environments(self): | |
| self.send_response(200) | |
| self.send_header("Content-type", "application/json") | |
| self.end_headers() | |
| env_data = collect_environment_metrics() | |
| response = json.dumps(env_data, indent=2) | |
| self.wfile.write(response.encode()) | |
| def send_404(self): | |
| self.send_response(404) | |
| self.send_header("Content-type", "text/html") | |
| self.end_headers() | |
| self.wfile.write(b"404 Not Found") | |
| def log_message(self, format, *args): | |
| pass | |
| def collect_system_metrics(): | |
| """Collect system metrics using standard library""" | |
| try: | |
| import psutil | |
| cpu_percent = psutil.cpu_percent(interval=1) | |
| memory = psutil.virtual_memory() | |
| disk = psutil.disk_usage("/") | |
| return { | |
| "cpu_percent": cpu_percent, | |
| "memory_percent": memory.percent, | |
| "memory_available_gb": memory.available / (1024**3), | |
| "disk_percent": disk.percent, | |
| "disk_free_gb": disk.free / (1024**3), | |
| "uptime": time.strftime("%H:%M:%S", time.gmtime(time.time() - start_time)), | |
| "timestamp": datetime.now().isoformat(), | |
| "process_count": len(psutil.pids()), | |
| } | |
| except ImportError: | |
| import random | |
| cpu = random.uniform(20, 80) | |
| memory = random.uniform(30, 70) | |
| disk = random.uniform(40, 60) | |
| return { | |
| "cpu_percent": cpu, | |
| "memory_percent": memory, | |
| "memory_available_gb": random.uniform(2, 8), | |
| "disk_percent": disk, | |
| "disk_free_gb": random.uniform(10, 50), | |
| "uptime": time.strftime("%H:%M:%S", time.gmtime(time.time() - start_time)), | |
| "timestamp": datetime.now().isoformat(), | |
| "process_count": random.randint(100, 300), | |
| } | |
| def collect_environment_metrics(): | |
| """Collect blue-green environment health metrics""" | |
| environments = {} | |
| # Check Blue Environment (port 5002) | |
| blue_health = check_environment_health("localhost", 5002) | |
| environments["blue_environment"] = blue_health | |
| # Check Green Environment (port 5003) | |
| green_health = check_environment_health("localhost", 5003) | |
| environments["green_environment"] = green_health | |
| environments["timestamp"] = datetime.now().isoformat() | |
| return environments | |
| def check_environment_health(host, port): | |
| """Check if environment is healthy""" | |
| try: | |
| start_time = time.time() | |
| response = requests.get(f"http://{host}:{port}/api/health", timeout=5) | |
| response_time = (time.time() - start_time) * 1000 | |
| if response.status_code == 200: | |
| try: | |
| health_data = response.json() | |
| return { | |
| "healthy": True, | |
| "response_time": int(response_time), | |
| "status": "healthy", | |
| "version": health_data.get("version", "unknown"), | |
| "endpoint": f"http://{host}:{port}", | |
| "last_check": datetime.now().isoformat(), | |
| } | |
| except Exception: | |
| return { | |
| "healthy": True, | |
| "response_time": int(response_time), | |
| "status": "healthy", | |
| "endpoint": f"http://{host}:{port}", | |
| "last_check": datetime.now().isoformat(), | |
| } | |
| else: | |
| return { | |
| "healthy": False, | |
| "response_time": int(response_time), | |
| "status": "unhealthy", | |
| "error": f"HTTP {response.status_code}", | |
| "endpoint": f"http://{host}:{port}", | |
| "last_check": datetime.now().isoformat(), | |
| } | |
| except requests.exceptions.RequestException as e: | |
| return { | |
| "healthy": False, | |
| "response_time": 5000, | |
| "status": "unreachable", | |
| "error": str(e), | |
| "endpoint": f"http://{host}:{port}", | |
| "last_check": datetime.now().isoformat(), | |
| } | |
| except Exception as e: | |
| return { | |
| "healthy": False, | |
| "response_time": 0, | |
| "status": "error", | |
| "error": str(e), | |
| "endpoint": f"http://{host}:{port}", | |
| "last_check": datetime.now().isoformat(), | |
| } | |
| def run_server(): | |
| """Run the monitoring server""" | |
| server_address = ("", 8080) | |
| httpd = HTTPServer(server_address, MonitoringDashboardHandler) | |
| print("π Production Monitoring Dashboard started!") | |
| print("π Access URL: http://localhost:8080") | |
| print("π Blue-Green Environment Monitoring: Enabled") | |
| print("π Auto-refresh: Every 5 seconds") | |
| print("βΉοΈ To stop: Press Ctrl+C") | |
| print("") | |
| try: | |
| httpd.serve_forever() | |
| except KeyboardInterrupt: | |
| print("\\nπ Dashboard stopped by user") | |
| httpd.server_close() | |
| if __name__ == "__main__": | |
| start_time = time.time() | |
| run_server() | |