# Automated Service Health Monitor

This tool runs periodically to check the health of a list of websites. If a site is down, it logs the error and sends an email alert.

**Modules Used:**
*   [[programming/python/modules/schedule-module|schedule]]: To run the check periodically.
*   [[programming/python/modules/requests-module|requests]]: To check the HTTP status.
*   [[programming/python/modules/smtplib-module|smtplib]]: To send email alerts.
*   [[programming/python/modules/python-dotenv-module|python-dotenv]]: To manage credentials securely.
*   [[programming/python/modules/logging-module|logging]]: To keep a history of checks.

## Setup

Create a `.env` file:
```text
EMAIL_USER=your_email@gmail.com
EMAIL_PASS=your_app_password
ALERT_RECEIVER=admin@example.com
```

## The Code

Save this as `monitor.py`.

```python
import schedule
import time
import requests
import smtplib
import logging
import os
from dotenv import load_dotenv
from email.message import EmailMessage

# Load config
load_dotenv()

# Configure Logging
logging.basicConfig(
    filename='monitor.log', 
    level=logging.INFO, 
    format='%(asctime)s - %(levelname)s - %(message)s'
)

SITES_TO_CHECK = [
    "https://www.google.com",
    "https://www.github.com",
    "https://httpbin.org/status/500" # Intentionally broken link for testing
]

def send_alert(site, status):
    """Sends an email alert."""
    msg = EmailMessage()
    msg.set_content(f"ALERT: {site} is down! Status Code: {status}")
    msg['Subject'] = f"Downtime Alert: {site}"
    msg['From'] = os.getenv("EMAIL_USER")
    msg['To'] = os.getenv("ALERT_RECEIVER")

    try:
        with smtplib.SMTP_SSL('smtp.gmail.com', 465) as server:
            server.login(os.getenv("EMAIL_USER"), os.getenv("EMAIL_PASS"))
            server.send_message(msg)
        logging.info(f"Alert sent for {site}")
    except Exception as e:
        logging.error(f"Failed to send alert: {e}")

def check_sites():
    print("Running health check...")
    for site in SITES_TO_CHECK:
        try:
            r = requests.get(site, timeout=5)
            if r.status_code != 200:
                logging.warning(f"{site} returned {r.status_code}")
                send_alert(site, r.status_code)
            else:
                logging.info(f"{site} is UP")
        except Exception as e:
            logging.error(f"{site} is UNREACHABLE: {e}")
            send_alert(site, "Unreachable")

# Run every 10 minutes
schedule.every(10).minutes.do(check_sites)

if __name__ == "__main__":
    # Run once immediately on startup
    check_sites()
    
    while True:
        schedule.run_pending()
        time.sleep(1)
```

[[programming/python/python]]