From e88aeb2cb19f03a15b0c3e43877344fce29b635d Mon Sep 17 00:00:00 2001 From: Noran-Salm Date: Mon, 27 Jul 2026 19:07:35 +0300 Subject: [PATCH] Initial deployment --- Dockerfile | 16 +++ app.py | 38 ++++++ dashboard.html | 293 ++++++++++++++++++++++++++++++++++++++++++ health-check.sh | 38 ++++++ monitoring-data.json | 296 +++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 1 + update_monitor.py | 31 +++++ 7 files changed, 713 insertions(+) create mode 100644 Dockerfile create mode 100644 app.py create mode 100644 dashboard.html create mode 100644 health-check.sh create mode 100644 monitoring-data.json create mode 100644 requirements.txt create mode 100644 update_monitor.py diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a67ee7a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM python:3.11-slim + +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + +WORKDIR /app + +COPY requirements.txt . + +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +EXPOSE 5000 + +CMD ["python", "app.py"] \ No newline at end of file diff --git a/app.py b/app.py new file mode 100644 index 0000000..265475f --- /dev/null +++ b/app.py @@ -0,0 +1,38 @@ +from flask import Flask, jsonify +import time + +app = Flask(__name__) + +request_count = 0 +start_time = time.time() + + +@app.route("/") +def home(): + global request_count + request_count += 1 + return jsonify({ + "message": "Hello from Ghaymah!", + "timestamp": time.time() + }) + + +@app.route("/health") +def health(): + global request_count + request_count += 1 + return jsonify({ + "status": "healthy" + }) + + +@app.route("/metrics") +def metrics(): + return jsonify({ + "request_count": request_count, + "uptime": round(time.time() - start_time, 2) + }) + + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=5000) \ No newline at end of file diff --git a/dashboard.html b/dashboard.html new file mode 100644 index 0000000..9ab6cb0 --- /dev/null +++ b/dashboard.html @@ -0,0 +1,293 @@ + + + + + + API Monitoring Dashboard + + + + + +
+

πŸ“Š API Monitoring Dashboard

+ + +
+
+
Uptime (24h)
+
--
+
+
+
Current Status
+
--
+
+
+
Last Latency
+
--
+
milliseconds
+
+
+
Total Requests
+
--
+
+
+ + +
+ +
+ + +
+

Recent Checks (last 10)

+ + + + + + + + + + + + +
TimestampStatusLatency (ms)Request Count
Loading data…
+
+
+ + + + \ No newline at end of file diff --git a/health-check.sh b/health-check.sh new file mode 100644 index 0000000..b2331a3 --- /dev/null +++ b/health-check.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +URL="http://localhost:5000" + +REQUESTS=0 + +while true +do + REQUESTS=$((REQUESTS+1)) + + RESPONSE=$(curl -o /dev/null -s -w "%{http_code} %{time_total}" "$URL/health") + + STATUS_CODE=$(echo "$RESPONSE" | cut -d' ' -f1) + RESPONSE_TIME=$(echo "$RESPONSE" | cut -d' ' -f2) + + if [ "$STATUS_CODE" = "200" ] + then + STATUS="UP" + else + STATUS="DOWN" + fi + + TIMESTAMP=$(date -Iseconds) + LATENCY_MS=$(awk "BEGIN {print $RESPONSE_TIME * 1000}") + + python update_monitor.py \ + "$TIMESTAMP" \ + "$(echo $STATUS | tr '[:upper:]' '[:lower:]')" \ + "$LATENCY_MS" \ + "$REQUESTS" + + echo "Status : $STATUS" + echo "Latency : ${LATENCY_MS} ms" + echo "Requests : $REQUESTS" + echo "-------------------------" + + sleep 30 +done \ No newline at end of file diff --git a/monitoring-data.json b/monitoring-data.json new file mode 100644 index 0000000..4841047 --- /dev/null +++ b/monitoring-data.json @@ -0,0 +1,296 @@ +[ + { + "timestamp": "2026-07-27T03:10:22+03:00", + "status": "up", + "latency": 9.449, + "request_count": 1 + }, + { + "timestamp": "2026-07-27T03:10:53+03:00", + "status": "up", + "latency": 7.223, + "request_count": 2 + }, + { + "timestamp": "2026-07-27T03:11:24+03:00", + "status": "up", + "latency": 5.266, + "request_count": 3 + }, + { + "timestamp": "2026-07-27T03:11:54+03:00", + "status": "up", + "latency": 5.777, + "request_count": 4 + }, + { + "timestamp": "2026-07-27T03:12:25+03:00", + "status": "up", + "latency": 10.061, + "request_count": 5 + }, + { + "timestamp": "2026-07-27T03:12:55+03:00", + "status": "up", + "latency": 6.11, + "request_count": 6 + }, + { + "timestamp": "2026-07-27T03:13:26+03:00", + "status": "up", + "latency": 25.41, + "request_count": 7 + }, + { + "timestamp": "2026-07-27T03:13:56+03:00", + "status": "up", + "latency": 16.302, + "request_count": 8 + }, + { + "timestamp": "2026-07-27T03:14:27+03:00", + "status": "up", + "latency": 11.741, + "request_count": 9 + }, + { + "timestamp": "2026-07-27T03:14:58+03:00", + "status": "up", + "latency": 26.753, + "request_count": 10 + }, + { + "timestamp": "2026-07-27T03:15:28+03:00", + "status": "up", + "latency": 13.328, + "request_count": 11 + }, + { + "timestamp": "2026-07-27T03:15:59+03:00", + "status": "up", + "latency": 6.945, + "request_count": 12 + }, + { + "timestamp": "2026-07-27T03:16:29+03:00", + "status": "up", + "latency": 8.735, + "request_count": 13 + }, + { + "timestamp": "2026-07-27T03:16:59+03:00", + "status": "up", + "latency": 7.036, + "request_count": 14 + }, + { + "timestamp": "2026-07-27T03:17:30+03:00", + "status": "up", + "latency": 13.428, + "request_count": 15 + }, + { + "timestamp": "2026-07-27T03:18:00+03:00", + "status": "up", + "latency": 7.623, + "request_count": 16 + }, + { + "timestamp": "2026-07-27T03:18:31+03:00", + "status": "up", + "latency": 77.742, + "request_count": 17 + }, + { + "timestamp": "2026-07-27T03:19:02+03:00", + "status": "up", + "latency": 5.957, + "request_count": 18 + }, + { + "timestamp": "2026-07-27T03:19:32+03:00", + "status": "up", + "latency": 11.503, + "request_count": 19 + }, + { + "timestamp": "2026-07-27T03:20:03+03:00", + "status": "up", + "latency": 8.375, + "request_count": 20 + }, + { + "timestamp": "2026-07-27T03:20:33+03:00", + "status": "up", + "latency": 8.342, + "request_count": 21 + }, + { + "timestamp": "2026-07-27T03:21:04+03:00", + "status": "up", + "latency": 33.106, + "request_count": 22 + }, + { + "timestamp": "2026-07-27T03:21:34+03:00", + "status": "up", + "latency": 7.304, + "request_count": 23 + }, + { + "timestamp": "2026-07-27T03:22:05+03:00", + "status": "up", + "latency": 36.75, + "request_count": 24 + }, + { + "timestamp": "2026-07-27T03:22:35+03:00", + "status": "up", + "latency": 9.297, + "request_count": 25 + }, + { + "timestamp": "2026-07-27T03:23:06+03:00", + "status": "up", + "latency": 12.333, + "request_count": 26 + }, + { + "timestamp": "2026-07-27T03:23:36+03:00", + "status": "up", + "latency": 8.061, + "request_count": 27 + }, + { + "timestamp": "2026-07-27T03:24:07+03:00", + "status": "up", + "latency": 10.166, + "request_count": 28 + }, + { + "timestamp": "2026-07-27T03:24:37+03:00", + "status": "up", + "latency": 5.104, + "request_count": 29 + }, + { + "timestamp": "2026-07-27T03:25:08+03:00", + "status": "up", + "latency": 27.727, + "request_count": 30 + }, + { + "timestamp": "2026-07-27T03:25:38+03:00", + "status": "up", + "latency": 7.573, + "request_count": 31 + }, + { + "timestamp": "2026-07-27T03:26:09+03:00", + "status": "up", + "latency": 6.931, + "request_count": 32 + }, + { + "timestamp": "2026-07-27T03:26:39+03:00", + "status": "up", + "latency": 7.046, + "request_count": 33 + }, + { + "timestamp": "2026-07-27T03:27:10+03:00", + "status": "up", + "latency": 9.342, + "request_count": 34 + }, + { + "timestamp": "2026-07-27T03:27:40+03:00", + "status": "up", + "latency": 6.77, + "request_count": 35 + }, + { + "timestamp": "2026-07-27T03:28:11+03:00", + "status": "up", + "latency": 6.837, + "request_count": 36 + }, + { + "timestamp": "2026-07-27T03:28:41+03:00", + "status": "up", + "latency": 9.652, + "request_count": 37 + }, + { + "timestamp": "2026-07-27T03:29:12+03:00", + "status": "up", + "latency": 15.207, + "request_count": 38 + }, + { + "timestamp": "2026-07-27T03:29:43+03:00", + "status": "up", + "latency": 10.94, + "request_count": 39 + }, + { + "timestamp": "2026-07-27T03:30:13+03:00", + "status": "up", + "latency": 6.731, + "request_count": 40 + }, + { + "timestamp": "2026-07-27T03:30:44+03:00", + "status": "up", + "latency": 7.411, + "request_count": 41 + }, + { + "timestamp": "2026-07-27T03:31:15+03:00", + "status": "up", + "latency": 13.245, + "request_count": 42 + }, + { + "timestamp": "2026-07-27T03:31:45+03:00", + "status": "up", + "latency": 6.691, + "request_count": 43 + }, + { + "timestamp": "2026-07-27T03:32:16+03:00", + "status": "up", + "latency": 7.81, + "request_count": 44 + }, + { + "timestamp": "2026-07-27T03:32:46+03:00", + "status": "up", + "latency": 22.151, + "request_count": 45 + }, + { + "timestamp": "2026-07-27T03:33:16+03:00", + "status": "up", + "latency": 7.746, + "request_count": 46 + }, + { + "timestamp": "2026-07-27T03:33:47+03:00", + "status": "up", + "latency": 10.829, + "request_count": 47 + }, + { + "timestamp": "2026-07-27T03:34:18+03:00", + "status": "up", + "latency": 18.731, + "request_count": 48 + }, + { + "timestamp": "2026-07-27T03:34:48+03:00", + "status": "up", + "latency": 9.383, + "request_count": 49 + } +] \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..cc35792 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +Flask==2.3.3 \ No newline at end of file diff --git a/update_monitor.py b/update_monitor.py new file mode 100644 index 0000000..80db841 --- /dev/null +++ b/update_monitor.py @@ -0,0 +1,31 @@ +import json +import os +import sys + +FILE = "monitoring-data.json" +MAX_ENTRIES = 100 + +entry = { + "timestamp": sys.argv[1], + "status": sys.argv[2], + "latency": float(sys.argv[3]), + "request_count": int(sys.argv[4]) +} + +if os.path.exists(FILE): + try: + with open(FILE, "r") as f: + data = json.load(f) + if not isinstance(data, list): + data = [] + except Exception: + data = [] +else: + data = [] + +data.append(entry) + +data = data[-MAX_ENTRIES:] + +with open(FILE, "w") as f: + json.dump(data, f, indent=2) \ No newline at end of file