#!/usr/bin/env python3 """ Feed Hunter Monitor Status Checker Shows the current status of the monitoring system and recent alerts """ import json import sys from datetime import datetime, timezone, timedelta from pathlib import Path PROJECT_DIR = Path(__file__).parent STATUS_FILE = PROJECT_DIR / "data" / "monitor_status.json" def load_monitor_status() -> dict: """Load monitor status from file""" if STATUS_FILE.exists(): try: return json.loads(STATUS_FILE.read_text()) except: pass return { "alert_timestamps": [], "last_portal_up": None, "last_chrome_up": None, "consecutive_chrome_failures": 0, "consecutive_portal_failures": 0, "last_successful_scrape": None, } def format_timestamp(ts): """Format timestamp for display""" if not ts: return "Never" try: dt = datetime.fromtimestamp(ts, tz=timezone.utc) return dt.strftime("%Y-%m-%d %H:%M:%S UTC") except: return str(ts) def format_time_ago(ts): """Format time ago for display""" if not ts: return "Never" try: dt = datetime.fromtimestamp(ts, tz=timezone.utc) now = datetime.now(timezone.utc) diff = now - dt if diff.total_seconds() < 60: return f"{int(diff.total_seconds())}s ago" elif diff.total_seconds() < 3600: return f"{int(diff.total_seconds() / 60)}m ago" else: return f"{int(diff.total_seconds() / 3600)}h ago" except: return str(ts) def main(): """Main status display""" status = load_monitor_status() now = datetime.now(timezone.utc) print("=== Feed Hunter Monitor Status ===") print(f"Current time: {now.strftime('%Y-%m-%d %H:%M:%S UTC')}") print() # Portal status print("🌐 Portal Status:") if status["consecutive_portal_failures"] == 0: print(f" ✅ UP (last seen: {format_time_ago(status['last_portal_up'])})") else: print(f" ❌ DOWN ({status['consecutive_portal_failures']} consecutive failures)") print(f" Last UP: {format_time_ago(status['last_portal_up'])}") print() # Chrome status print("🔧 Chrome Debug Port:") if status["consecutive_chrome_failures"] == 0: print(f" ✅ UP (last seen: {format_time_ago(status['last_chrome_up'])})") else: print(f" ❌ DOWN ({status['consecutive_chrome_failures']} consecutive failures)") print(f" Last UP: {format_time_ago(status['last_chrome_up'])}") print() # Recent alerts now_ts = int(now.timestamp()) recent_alerts = [ts for ts in status["alert_timestamps"] if now_ts - ts < 3600] print("📢 Alert Status:") print(f" Recent alerts (last hour): {len(recent_alerts)}") print(f" Rate limit status: {len(recent_alerts)}/3 per hour") print() # System health summary print("📊 System Health Summary:") if status["consecutive_portal_failures"] == 0 and status["consecutive_chrome_failures"] == 0: print(" 🟢 All systems operational") elif status["consecutive_portal_failures"] > 0 or status["consecutive_chrome_failures"] > 3: print(" 🔴 Critical issues detected") else: print(" 🟡 Minor issues detected") print() # Service status print("⚙️ Systemd Services:") try: import subprocess # Check if timers are active result = subprocess.run( ["systemctl", "--user", "is-active", "feed-hunter-portal-monitor-business.timer"], capture_output=True, text=True ) business_timer = result.stdout.strip() result = subprocess.run( ["systemctl", "--user", "is-active", "feed-hunter-portal-monitor-offhours.timer"], capture_output=True, text=True ) offhours_timer = result.stdout.strip() print(f" Business Hours Timer: {business_timer}") print(f" Off-Hours Timer: {offhours_timer}") # Show next scheduled runs result = subprocess.run( ["systemctl", "--user", "list-timers", "feed-hunter-portal-monitor-*"], capture_output=True, text=True ) if result.returncode == 0 and result.stdout: print("\n 📅 Next scheduled runs:") lines = result.stdout.split('\n') for line in lines[1:]: # Skip header if 'feed-hunter-portal-monitor' in line: print(f" {line.strip()}") except Exception as e: print(f" Error checking systemd status: {e}") if __name__ == "__main__": main()