Files
workspace/projects/feed-hunter/monitor_status.py

143 lines
4.6 KiB
Python
Executable File

#!/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()