143 lines
4.6 KiB
Python
Executable File
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() |