import asyncio import json import subprocess import psutil from datetime import datetime, timedelta from typing import Dict, Any, Optional, List from dash import Output, Input, State, html, callback_context, no_update import dash_bootstrap_components as dbc from utils.logger import get_logger from database.connection import DatabaseManager from database.redis_manager import get_sync_redis_manager from config.constants.system_health_constants import ( CPU_GOOD_THRESHOLD, CPU_WARNING_THRESHOLD, MEMORY_GOOD_THRESHOLD, MEMORY_WARNING_THRESHOLD ) logger = get_logger("default_logger") def register_quick_status_callbacks(app): """Register quick status callbacks (top cards).""" @app.callback( [Output('data-collection-quick-status', 'children'), Output('database-quick-status', 'children'), Output('redis-quick-status', 'children'), Output('performance-quick-status', 'children')], Input('interval-component', 'n_intervals') ) def update_quick_status(n_intervals): """Update quick status indicators.""" try: dc_status = _get_data_collection_quick_status() db_status = _get_database_quick_status() redis_status = _get_redis_quick_status() perf_status = _get_performance_quick_status() return dc_status, db_status, redis_status, perf_status except Exception as e: logger.error(f"Error updating quick status: {e}") error_status = dbc.Badge("🔴 Error", color="danger", className="me-1") return error_status, error_status, error_status, error_status def _get_data_collection_quick_status() -> dbc.Badge: """Get quick data collection status.""" try: is_running = _check_data_collection_service_running() if is_running: return dbc.Badge("Active", color="success", className="me-1") else: return dbc.Badge("Stopped", color="danger", className="me-1") except Exception as e: logger.error(f"Error checking data collection quick status: {e}") return dbc.Badge("Unknown", color="warning", className="me-1") def _get_database_quick_status() -> dbc.Badge: """Get quick database status.""" try: db_manager = DatabaseManager() db_manager.initialize() if db_manager.test_connection(): return dbc.Badge("Connected", color="success", className="me-1") else: return dbc.Badge("Error", color="danger", className="me-1") except Exception as e: logger.error(f"Error checking database quick status: {e}") return dbc.Badge("Error", color="danger", className="me-1") def _get_redis_quick_status() -> dbc.Badge: """Get quick Redis status.""" try: redis_manager = get_sync_redis_manager() redis_manager.initialize() if redis_manager.client.ping(): return dbc.Badge("Connected", color="success", className="me-1") else: return dbc.Badge("Error", color="danger", className="me-1") except Exception as e: logger.error(f"Redis quick status check failed: {e}") return dbc.Badge("Error", color="danger", className="me-1") def _get_performance_quick_status() -> dbc.Badge: """Get quick performance status.""" try: cpu_percent = psutil.cpu_percent(interval=0.1) memory = psutil.virtual_memory() if cpu_percent < CPU_GOOD_THRESHOLD and memory.percent < MEMORY_GOOD_THRESHOLD: return dbc.Badge("Good", color="success", className="me-1") elif cpu_percent < CPU_WARNING_THRESHOLD and memory.percent < MEMORY_WARNING_THRESHOLD: return dbc.Badge("Warning", color="warning", className="me-1") else: return dbc.Badge("High", color="danger", className="me-1") except Exception as e: logger.error(f"Error checking performance quick status: {e}") return dbc.Badge("Unknown", color="secondary", className="me-1") def _check_data_collection_service_running() -> bool: """Check if data collection service is running.""" try: for proc in psutil.process_iter(['pid', 'name', 'cmdline']): try: if proc.info['cmdline']: cmdline = ' '.join(proc.info['cmdline']) if 'start_data_collection.py' in cmdline or 'collection_service' in cmdline: return True except (psutil.NoSuchProcess, psutil.AccessDenied) as e: logger.warning(f"Access or process error checking service: {e}") continue return False except Exception as e: logger.error(f"Error checking data collection service running status: {e}") return False