diff --git a/q5-mithal-monitor/Dockerfile b/q5-mithal-monitor/Dockerfile index 4e0ba83..98d4a6b 100644 --- a/q5-mithal-monitor/Dockerfile +++ b/q5-mithal-monitor/Dockerfile @@ -8,8 +8,6 @@ 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" +CMD ["python3","app.py"] diff --git a/q5-mithal-monitor/app.py b/q5-mithal-monitor/app.py new file mode 100644 index 0000000..5d5d564 --- /dev/null +++ b/q5-mithal-monitor/app.py @@ -0,0 +1,51 @@ +from flask import Flask, send_file, jsonify +import threading +import time +import json +import os + +from monitor import collect_metrics + +app = Flask(__name__) + + +def monitor_loop(): + while True: + try: + collect_metrics() + print("Metrics updated.") + except Exception as e: + print("Monitor error:", e) + + time.sleep(60) + + +@app.route("/") +def dashboard(): + return send_file("dashboard.html") + + +@app.route("/metrics.json") +def metrics(): + if os.path.exists("metrics.json"): + with open("metrics.json") as f: + return jsonify(json.load(f)) + + return jsonify({ + "uptime": 0, + "last_check": {}, + "history": [], + "latency_chart": [] + }) + + +if __name__ == "__main__": + # Run one check immediately + collect_metrics() + + # Start background monitoring + thread = threading.Thread(target=monitor_loop, daemon=True) + thread.start() + + # Start Flask + app.run(host="0.0.0.0", port=8080) diff --git a/q5-mithal-monitor/dashboard.html b/q5-mithal-monitor/dashboard.html index 5882bed..05f9058 100644 --- a/q5-mithal-monitor/dashboard.html +++ b/q5-mithal-monitor/dashboard.html @@ -8,255 +8,195 @@ - + -

🚀 Mithal Monitoring Dashboard

+

Mithal Monitoring Dashboard

-

Uptime (24h)

-
-- %
+

Uptime

+
--

Latency

-
-- ms
+
--
-

DNS Lookup

-
-- ms
+

DNS

+
--
-

Search Response

- +

Search

+

SSL Expiry

-
--
+
--
-

Days Remaining

+

Days Left

--
- + + + - - - +
Time Status Latency DNS Search SSL Days
diff --git a/q5-mithal-monitor/metrics.json b/q5-mithal-monitor/metrics.json deleted file mode 100644 index 92b1b69..0000000 --- a/q5-mithal-monitor/metrics.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "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 index e221f38..0b7d6f4 100644 --- a/q5-mithal-monitor/monitor.py +++ b/q5-mithal-monitor/monitor.py @@ -11,139 +11,82 @@ URL = "https://mithal.space" OUTPUT_FILE = "metrics.json" -def http_check(): +def collect_metrics(): + hostname = urlparse(URL).hostname + + # HTTP latency & uptime start = time.time() - try: - r = requests.get(URL, timeout=10) + response = 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 + status = response.status_code + except Exception: + latency = -1 + status = 0 + # DNS lookup start = time.time() - try: - socket.gethostbyname(host) - except: - pass - - return round((time.time() - start) * 1000, 2) - - -def ssl_info(): - - host = urlparse(URL).hostname + socket.gethostbyname(hostname) + dns = round((time.time() - start) * 1000, 2) + except Exception: + dns = -1 + # SSL expiry + ssl_expiry = "Unavailable" + ssl_days = -1 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: - + context = ssl.create_default_context() + with socket.create_connection((hostname, 443), timeout=10) as sock: + with context.wrap_socket(sock, server_hostname=hostname) 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: + expiry = datetime.strptime(cert["notAfter"], "%b %d %H:%M:%S %Y %Z") + ssl_expiry = expiry.strftime("%Y-%m-%d") + ssl_days = (expiry - datetime.utcnow()).days + except Exception: pass - return round((time.time()-start)*1000,2) + # Search response + start = time.time() + try: + requests.get(URL, timeout=10) + search_latency = round((time.time() - start) * 1000, 2) + except Exception: + search_latency = -1 + if os.path.exists(OUTPUT_FILE): + with open(OUTPUT_FILE) as f: + data = json.load(f) + else: + data = {"history": []} -if os.path.exists(OUTPUT_FILE): + history = data.get("history", []) - with open(OUTPUT_FILE,"r") as f: + history.append({ + "time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + "status": status, + "latency": latency, + "dns": dns, + "ssl_expiry": ssl_expiry, + "ssl_days_left": ssl_days, + "search_latency": search_latency + }) - data=json.load(f) + history = history[-1440:] -else: - - data={ - - "history":[] + uptime = round( + len([x for x in history if x["status"] == 200]) / + len(history) * 100, + 2 + ) + output = { + "uptime": uptime, + "last_check": history[-1], + "history": history[-10:], + "latency_chart": [x["latency"] for x in history[-60:]] } -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,"%") + with open(OUTPUT_FILE, "w") as f: + json.dump(output, f, indent=4) diff --git a/q5-mithal-monitor/requirements.txt b/q5-mithal-monitor/requirements.txt index f229360..e635204 100644 --- a/q5-mithal-monitor/requirements.txt +++ b/q5-mithal-monitor/requirements.txt @@ -1 +1,2 @@ +Flask requests