اعمل Uptime Monitor مجاني بتنبيه Telegram وGitHub Actions
مستوى القارئ: متوسط
هتطلع من المقال ده بمراقب uptime عملي: يفحص موقعك كل 5 دقائق، ويبعث لك رسالة Telegram لما الموقع يقع أو يرد ببطء.
المشكلة باختصار
لو عندك موقع صغير أو landing page أو API داخلي، غالبًا مش محتاج تبدأ بخدمة مراقبة مدفوعة. المشكلة إنك برضه محتاج تعرف بسرعة لو الموقع وقع. الانتظار لحد ما عميل يكلّمك هو أسوأ طريقة.
السيناريو الواقعي هنا: موقع بيزوره 20K زائر يوميًا، وصفحة الدفع فيه بتعمل timeout لمدة 12 دقيقة. لو متوسط الطلبات 14 طلب في الدقيقة، فأنت ممكن تخسر حوالي 168 محاولة شراء قبل ما تلاحظ المشكلة. مراقب بسيط ينبهك خلال 5 دقائق يقلل الخسارة بشكل واضح.
الافتراض إن عندك موقع واحد أو 3 مواقع، ومحتاج تنبيه سريع، مش نظام incident management كامل. لو عايز SLA رسمي، escalation، وon-call rotations، استخدم أداة متخصصة.
الفكرة بالظبط
بدل ما تشغّل سيرفر مخصوص للمراقبة، هنستخدم GitHub Actions كـ scheduler. الـ workflow يشتغل كل 5 دقائق. يشغّل سكربت Python. السكربت يعمل GET على الموقع بمهلة 10 ثواني. لو الرد مش 2xx أو الزمن أعلى من الحد اللي حددته، يبعت رسالة Telegram.
الـ trade-off هنا واضح: بتكسب حل مجاني وسريع الإعداد. بتخسر دقة أعلى في التوقيت، لأن GitHub Actions ممكن يتأخر وقت الضغط، وبتخسر تاريخ metrics طويل إلا لو خزّنته بنفسك.
الخطوات التنفيذية
- اعمل Telegram bot من BotFather وخد التوكن.
- ابعت رسالة للبوت من حسابك، ثم هات chat_id من تحديثات البوت أو من أداة موثوقة تعرضه لك.
- في GitHub repo جديد، أضف secrets باسم
TELEGRAM_BOT_TOKENوTELEGRAM_CHAT_ID. - أضف secret ثالث باسم
CHECK_URLوقيمته رابط الموقع، مثلhttps://example.com/health. - أنشئ ملف
monitor.pyفي جذر المشروع. - أنشئ workflow داخل
.github/workflows/uptime.yml. - اختبره يدويًا أول مرة من تبويب Actions قبل الاعتماد عليه.
سكربت الفحص
ركز في نقطتين: استخدم timeout صريح، ولا تعتبر أي status code ناجح. الأفضل إن endpoint الصحة يرجع 200 فقط عندما التطبيق والـ DB والخدمات الأساسية شغالة.
import os
import time
import requests
CHECK_URL = os.environ["CHECK_URL"]
BOT_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]
CHAT_ID = os.environ["TELEGRAM_CHAT_ID"]
MAX_MS = int(os.getenv("MAX_RESPONSE_MS", "1500"))
def send_telegram(message: str) -> None:
url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage"
requests.post(
url,
json={"chat_id": CHAT_ID, "text": message},
timeout=10,
).raise_for_status()
def main() -> None:
started = time.perf_counter()
try:
response = requests.get(CHECK_URL, timeout=10)
elapsed_ms = int((time.perf_counter() - started) * 1000)
if response.status_code < 200 or response.status_code >= 300:
send_telegram(
f"DOWN: {CHECK_URL} returned {response.status_code} in {elapsed_ms}ms"
)
raise SystemExit(1)
if elapsed_ms > MAX_MS:
send_telegram(
f"SLOW: {CHECK_URL} took {elapsed_ms}ms, limit is {MAX_MS}ms"
)
raise SystemExit(1)
print(f"OK: {CHECK_URL} responded in {elapsed_ms}ms")
except requests.RequestException as exc:
send_telegram(f"DOWN: {CHECK_URL} failed with {type(exc).__name__}: {exc}")
raise SystemExit(1)
if __name__ == "__main__":
main()