#!/usr/bin/env python3 """ Monitoring Script for Ghayma REST API Scans the application health endpoint every 30 seconds and logs results. """ import urllib.request import urllib.error import json import time import datetime import os import sys # Configuration APP_URL = os.environ.get("APP_URL", "http://localhost:3000") HEALTH_ENDPOINT = f"{APP_URL}/health" CHECK_INTERVAL = 30 # seconds LOG_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "monitor.log") TIMEOUT = 5 # seconds # ANSI colors for terminal output GREEN = "\033[92m" RED = "\033[91m" YELLOW = "\033[93m" CYAN = "\033[96m" RESET = "\033[0m" BOLD = "\033[1m" def log(message, level="INFO"): """Log a message to both console and log file.""" timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") log_entry = f"[{timestamp}] [{level}] {message}" # Color-coded console output if level == "OK": print(f"{GREEN}{log_entry}{RESET}") elif level == "ERROR": print(f"{RED}{BOLD}{log_entry}{RESET}") elif level == "WARN": print(f"{YELLOW}{log_entry}{RESET}") else: print(f"{CYAN}{log_entry}{RESET}") # Append to log file with open(LOG_FILE, "a", encoding="utf-8") as f: f.write(log_entry + "\n") def check_health(): """Send a GET request to the health endpoint and return the result.""" try: req = urllib.request.Request(HEALTH_ENDPOINT, method="GET") start_time = time.time() response = urllib.request.urlopen(req, timeout=TIMEOUT) response_time_ms = round((time.time() - start_time) * 1000) status_code = response.status body = json.loads(response.read().decode("utf-8")) return { "healthy": status_code == 200 and body.get("status") == "UP", "status_code": status_code, "response_time_ms": response_time_ms, "uptime": body.get("uptime"), "error": None, } except urllib.error.HTTPError as e: return { "healthy": False, "status_code": e.code, "response_time_ms": None, "uptime": None, "error": f"HTTP {e.code}: {e.reason}", } except urllib.error.URLError as e: return { "healthy": False, "status_code": None, "response_time_ms": None, "uptime": None, "error": f"Connection failed: {e.reason}", } except Exception as e: return { "healthy": False, "status_code": None, "response_time_ms": None, "uptime": None, "error": str(e), } def main(): consecutive_failures = 0 print(f"{BOLD}{CYAN}") print("=" * 55) print(" Ghayma REST API - Health Monitor") print(f" Target: {HEALTH_ENDPOINT}") print(f" Interval: {CHECK_INTERVAL}s") print(f" Log file: {LOG_FILE}") print("=" * 55) print(f"{RESET}") log(f"Monitor started | Target: {HEALTH_ENDPOINT} | Interval: {CHECK_INTERVAL}s") try: while True: result = check_health() if result["healthy"]: consecutive_failures = 0 uptime_str = f"{result['uptime']:.1f}s" if result["uptime"] else "N/A" log( f"HEALTHY | Status: {result['status_code']} | " f"Response: {result['response_time_ms']}ms | " f"Uptime: {uptime_str}", level="OK", ) else: consecutive_failures += 1 log( f"UNHEALTHY | Error: {result['error']} | " f"Consecutive failures: {consecutive_failures}", level="ERROR", ) if consecutive_failures >= 3: log( f"ALERT: {consecutive_failures} consecutive failures! " f"Application may be DOWN.", level="WARN", ) time.sleep(CHECK_INTERVAL) except KeyboardInterrupt: log("Monitor stopped by user.", level="INFO") print(f"\n{YELLOW}Monitor stopped.{RESET}") sys.exit(0) if __name__ == "__main__": main()