Build Your Own Server Monitoring System with Python and Discord Webhook

Python tutorial - IT technology blog
Python tutorial - IT technology blog

The Nightmare of “Midnight Server Crashes”

Are you managing a few VPS instances for web apps or bots? You’ve likely experienced that sinking feeling of waking up to find your services dead. Customers are complaining, your boss is calling, and the cause turns out to be something trivial: a full disk or a rogue process hogging all the RAM and freezing the machine.

Waking up to dozens of error notifications is a true nightmare. In reality, we can prevent this entirely if we monitor resource status in advance. Instead of manually SSHing into the server to run top or df -h every hour, I chose to let Python handle it. With just 15 minutes of setup, you’ll have a diligent “guardian” ready to message Discord whenever the system acts up.

When to Use Heavyweight Tools vs. Python?

Before diving into the code, let’s look at current monitoring solutions. Choosing the right tool will save you both time and money.

Comparing Popular Methods

  • Dedicated Tools (Prometheus, Zabbix): These are true “beasts.” They are powerful with beautiful dashboards but extremely resource-heavy. Running Prometheus + Grafana (which often consumes 200-400MB RAM) on a 1GB RAM VPS is just asking for trouble.
  • Cloud Services (Datadog, New Relic): Excellent features, but monthly costs can sometimes exceed the server rental price itself.
  • Custom Python Scripts: The optimal choice for startups or personal servers. It’s incredibly lightweight (consuming only about 15-20MB RAM), 100% customizable, and completely free.

The quick comparison table below will help you make a better decision:

Criteria Zabbix/Prometheus Python Script
RAM Consumption ~300MB+ < 20MB
Deployment Complex Very Fast
Cost Free/Paid $0

Why Discord Webhook?

Email is slow and easily ends up in spam. Telegram can sometimes face connectivity issues in certain regions. Meanwhile, Discord provides an extremely flexible Webhook mechanism. You just need to send a POST request with JSON to a predefined URL. Messages appear instantly with a professional Rich Embed format, allowing you to clearly distinguish the severity of alerts through colors.

Deploying the Monitoring Script in 3 Steps

To get started, your server needs Python 3. We will use psutil to read system metrics and requests to send data to Discord.

Step 1: Install Libraries

Run the following command in your server’s terminal:

pip install psutil requests

Step 2: Get the Webhook URL

  1. Open Discord, go to Server Settings -> Integrations.
  2. Select Webhooks -> New Webhook.
  3. Name your bot (e.g., “Sentry Bot”) and copy the URL. Keep this URL secret!

Step 3: Write the Processing Logic

The script below will check CPU, RAM, and Disk. If any metric exceeds the safety threshold, it will trigger an alarm.

import psutil
import requests
import socket
from datetime import datetime

# Alert threshold configuration
DISCORD_WEBHOOK_URL = "YOUR_WEBHOOK_URL_HERE"
CPU_THRESHOLD = 80  # Alert if CPU > 80%
RAM_THRESHOLD = 85  # Alert if RAM > 85%
DISK_THRESHOLD = 90 # Alert if Disk > 90%

def get_system_status():
    hostname = socket.gethostname()
    # Get average CPU over 1 second for accuracy
    cpu_usage = psutil.cpu_percent(interval=1)
    ram_usage = psutil.virtual_memory().percent
    disk_usage = psutil.disk_usage('/').percent
    return hostname, cpu_usage, ram_usage, disk_usage

def send_discord_alert(hostname, cpu, ram, disk):
    payload = {
        "embeds": [{
            "title": f"🚨 Resource Alert: {hostname}",
            "color": 15158332, # Red color
            "fields": [
                {"name": "CPU", "value": f"{cpu}%", "inline": True},
                {"name": "RAM", "value": f"{ram}%", "inline": True},
                {"name": "Disk", "value": f"{disk}%", "inline": True},
            ],
            "footer": {"text": f"Recorded at: {datetime.now().strftime('%H:%M:%S %d-%m-%Y')}"}
        }]
    }
    requests.post(DISCORD_WEBHOOK_URL, json=payload)

def main():
    hostname, cpu, ram, disk = get_system_status()
    if cpu > CPU_THRESHOLD or ram > RAM_THRESHOLD or disk > DISK_THRESHOLD:
        send_discord_alert(hostname, cpu, ram, disk)
    else:
        print(f"System stable: CPU {cpu}% | RAM {ram}% | Disk {disk}%")

if __name__ == "__main__":
    main()

Automation with Crontab

The script is finished, but you shouldn’t have to run it manually. To make it run automatically every 5 minutes, we use Crontab, the classic scheduling tool on Linux.

Type crontab -e and add this line to the end of the file:

*/5 * * * * /usr/bin/python3 /home/user/monitor.py >> /var/log/monitor.log 2>&1

Note: You should use absolute paths (e.g., /usr/bin/python3) to avoid environment errors when Cron executes.

Real-world Tips to Make Your Script “Smarter”

After running this on production clusters, here is some advice:

  1. Anti-Spam: If the CPU hangs at 90% continuously, your Discord will explode with notifications. Modify the code to only send messages when the status changes from “Normal” to “Alert”.
  2. Monitor OOM Killer: High RAM usage often leads to Linux killing heavy processes (like MySQL). You can add a psutil.process_iter() check to see if critical services are still running.
  3. Log Everything: Always log to a file. When the server actually crashes, these logs are your only clues to what happened at 2 AM.

Building your own monitoring tools not only gives you peace of mind but is also a great way to practice DevOps thinking. Wishing you many nights of sound sleep without worrying about sudden server “strokes”!

Share: