diff --git a/q5-mithal-monitor/Dockerfile b/q5-mithal-monitor/Dockerfile new file mode 100644 index 0000000..4e0ba83 --- /dev/null +++ b/q5-mithal-monitor/Dockerfile @@ -0,0 +1,15 @@ +FROM python:3.12-slim + +WORKDIR /app + +COPY requirements.txt . + +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +RUN mv dashboard.html index.html + +EXPOSE 8080 + +CMD sh -c "python3 monitor.py && python3 -m http.server 8080" diff --git a/q5-mithal-monitor/dashboard.html b/q5-mithal-monitor/dashboard.html new file mode 100644 index 0000000..5882bed --- /dev/null +++ b/q5-mithal-monitor/dashboard.html @@ -0,0 +1,264 @@ + + + + + +Mithal Monitoring Dashboard + + + + + + + + +

🚀 Mithal Monitoring Dashboard

+ +
+ +
+

Uptime (24h)

+
-- %
+
+ +
+

Latency

+
-- ms
+
+ +
+

DNS Lookup

+
-- ms
+
+ +
+

Search Response

+ +
+ +
+

SSL Expiry

+
--
+
+ +
+

Days Remaining

+
--
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +
TimeStatusLatencyDNSSearchSSL Days
+ + + + + diff --git a/q5-mithal-monitor/metrics.json b/q5-mithal-monitor/metrics.json new file mode 100644 index 0000000..92b1b69 --- /dev/null +++ b/q5-mithal-monitor/metrics.json @@ -0,0 +1,117 @@ +{ + "uptime": 100.0, + "last_check": { + "time": "2026-07-27 03:13:02", + "status": 200, + "latency": 78.62, + "dns": 0.5, + "search_latency": 80.38, + "ssl_expiry": "2026-09-15", + "ssl_days_left": 50 + }, + "history": [ + { + "time": "2026-07-27 03:04:01", + "status": 200, + "latency": 82.82, + "dns": 0.33, + "search_latency": 78.14, + "ssl_expiry": "2026-09-15", + "ssl_days_left": 50 + }, + { + "time": "2026-07-27 03:05:02", + "status": 200, + "latency": 89.55, + "dns": 0.31, + "search_latency": 76.35, + "ssl_expiry": "2026-09-15", + "ssl_days_left": 50 + }, + { + "time": "2026-07-27 03:06:01", + "status": 200, + "latency": 88.39, + "dns": 0.67, + "search_latency": 81.37, + "ssl_expiry": "2026-09-15", + "ssl_days_left": 50 + }, + { + "time": "2026-07-27 03:07:01", + "status": 200, + "latency": 77.25, + "dns": 3.21, + "search_latency": 80.14, + "ssl_expiry": "2026-09-15", + "ssl_days_left": 50 + }, + { + "time": "2026-07-27 03:08:01", + "status": 200, + "latency": 86.22, + "dns": 0.29, + "search_latency": 76.51, + "ssl_expiry": "2026-09-15", + "ssl_days_left": 50 + }, + { + "time": "2026-07-27 03:09:01", + "status": 200, + "latency": 81.52, + "dns": 0.55, + "search_latency": 74.89, + "ssl_expiry": "2026-09-15", + "ssl_days_left": 50 + }, + { + "time": "2026-07-27 03:10:01", + "status": 200, + "latency": 80.42, + "dns": 0.26, + "search_latency": 79.42, + "ssl_expiry": "2026-09-15", + "ssl_days_left": 50 + }, + { + "time": "2026-07-27 03:11:02", + "status": 200, + "latency": 82.46, + "dns": 0.5, + "search_latency": 75.56, + "ssl_expiry": "2026-09-15", + "ssl_days_left": 50 + }, + { + "time": "2026-07-27 03:12:01", + "status": 200, + "latency": 80.94, + "dns": 0.26, + "search_latency": 85.53, + "ssl_expiry": "2026-09-15", + "ssl_days_left": 50 + }, + { + "time": "2026-07-27 03:13:02", + "status": 200, + "latency": 78.62, + "dns": 0.5, + "search_latency": 80.38, + "ssl_expiry": "2026-09-15", + "ssl_days_left": 50 + } + ], + "latency_chart": [ + 78.97, + 82.82, + 89.55, + 88.39, + 77.25, + 86.22, + 81.52, + 80.42, + 82.46, + 80.94, + 78.62 + ] +} \ No newline at end of file diff --git a/q5-mithal-monitor/monitor.py b/q5-mithal-monitor/monitor.py new file mode 100644 index 0000000..e221f38 --- /dev/null +++ b/q5-mithal-monitor/monitor.py @@ -0,0 +1,149 @@ +import requests +import socket +import ssl +import time +import json +import os +from datetime import datetime +from urllib.parse import urlparse + +URL = "https://mithal.space" +OUTPUT_FILE = "metrics.json" + + +def http_check(): + start = time.time() + + try: + r = requests.get(URL, timeout=10) + latency = round((time.time() - start) * 1000, 2) + return r.status_code, latency + except: + latency = round((time.time() - start) * 1000, 2) + return 0, latency + + +def dns_lookup(): + host = urlparse(URL).hostname + + start = time.time() + + try: + socket.gethostbyname(host) + except: + pass + + return round((time.time() - start) * 1000, 2) + + +def ssl_info(): + + host = urlparse(URL).hostname + + try: + + ctx = ssl.create_default_context() + + with socket.create_connection((host,443),timeout=10) as sock: + + with ctx.wrap_socket(sock,server_hostname=host) as ssock: + + cert = ssock.getpeercert() + + expiry = datetime.strptime( + cert["notAfter"], + "%b %d %H:%M:%S %Y %Z" + ) + + days = (expiry-datetime.utcnow()).days + + return expiry.strftime("%Y-%m-%d"),days + + except: + + return "Unavailable",-1 + + +def search_response(): + + start=time.time() + + try: + requests.get(URL,timeout=10) + except: + pass + + return round((time.time()-start)*1000,2) + + +if os.path.exists(OUTPUT_FILE): + + with open(OUTPUT_FILE,"r") as f: + + data=json.load(f) + +else: + + data={ + + "history":[] + + } + +status,latency=http_check() + +record={ + +"time":datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + +"status":status, + +"latency":latency, + +"dns":dns_lookup(), + +"search_latency":search_response() + +} + +ssl_date,ssl_days=ssl_info() + +record["ssl_expiry"]=ssl_date +record["ssl_days_left"]=ssl_days + +data["history"].append(record) + +if len(data["history"])>1440: + + data["history"]=data["history"][-1440:] + +success=len([x for x in data["history"] if x["status"]==200]) + +uptime=round(success/len(data["history"])*100,2) + +output={ + +"uptime":uptime, + +"last_check":record, + +"history":data["history"][-10:], + +"latency_chart":[x["latency"] for x in data["history"][-60:]] + +} + +with open(OUTPUT_FILE,"w") as f: + + json.dump(output,f,indent=4) + +print("="*40) +print("Mithal Monitoring") +print("="*40) +print("Status :",status) +print("Latency :",latency,"ms") +print("DNS :",record["dns"],"ms") +print("Search :",record["search_latency"],"ms") +print("SSL Expiry :",ssl_date) +print("Days Left :",ssl_days) +print("Uptime :",uptime,"%") diff --git a/q5-mithal-monitor/requirements.txt b/q5-mithal-monitor/requirements.txt new file mode 100644 index 0000000..f229360 --- /dev/null +++ b/q5-mithal-monitor/requirements.txt @@ -0,0 +1 @@ +requests