From 2af6128a8d11bfaf20c797a798141bf56f63486b Mon Sep 17 00:00:00 2001 From: Abdelaiz Hassan Date: Wed, 29 Jul 2026 15:12:02 -0400 Subject: [PATCH] Remove unnecessary files --- common-mortakaz/integration-1.md | 0 common-mortakaz/integration-2.md | 0 common-qabilah/qabilah-profile.txt | 0 .../__pycache__/app.cpython-313.pyc | Bin 0 -> 1969 bytes q1-deploy-monitor/app.py | 46 +- q1-deploy-monitor/dashboard.html | 30 +- q3-cicd/workflow.yml | 23 +- q4-scalability/architecture.png | Bin 45463 -> 0 bytes q5-mithal-monitor/Dockerfile | 13 + q5-mithal-monitor/Start.sh | 11 + q5-mithal-monitor/monitor_data.json | 1000 +++++++++++++++++ q5-mithal-monitor/requirements.txt | 1 + 12 files changed, 1097 insertions(+), 27 deletions(-) delete mode 100644 common-mortakaz/integration-1.md delete mode 100644 common-mortakaz/integration-2.md delete mode 100644 common-qabilah/qabilah-profile.txt create mode 100644 q1-deploy-monitor/__pycache__/app.cpython-313.pyc delete mode 100644 q4-scalability/architecture.png create mode 100644 q5-mithal-monitor/Dockerfile create mode 100644 q5-mithal-monitor/Start.sh create mode 100644 q5-mithal-monitor/requirements.txt diff --git a/common-mortakaz/integration-1.md b/common-mortakaz/integration-1.md deleted file mode 100644 index e69de29..0000000 diff --git a/common-mortakaz/integration-2.md b/common-mortakaz/integration-2.md deleted file mode 100644 index e69de29..0000000 diff --git a/common-qabilah/qabilah-profile.txt b/common-qabilah/qabilah-profile.txt deleted file mode 100644 index e69de29..0000000 diff --git a/q1-deploy-monitor/__pycache__/app.cpython-313.pyc b/q1-deploy-monitor/__pycache__/app.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dd44628409fddc4d284bfac63e7f31f95cefe2be GIT binary patch literal 1969 zcma)6&2Jk;6rcU@+O^}P`EZ@Drc)Y}y3}zhwGbhMWQn4tfly^-A(2Ya)H}&;yWZW* zjO!+qkV6lx;6N`G6(CUwF5LR3ILe`Ai9`?=a&rh5IPqp3+aXe=jx;lG=Kbcq-@Nx` z4$|o)f;L;cefu*Vp+DrJ-LymD;4cuKAQPF&Ji4wh<+{pLEZ6G1#^|ERjqv*EYIh}x0gI#o6GUJ_7iP5gFrRn}gWfkdM2{6Kx^ZgFJ1iot@XVSyJtuBJqjdTQ89LsWP zjWC)NHW9eSNYJuF%A!hKY!eRv>>_qNE-102sY>LpV;nS&MWyrPAsRb^Q+EZQuh~x7 z#>B0Wbq>Bom3bV0K2zbj>Ex#r^E*y}%YM}p(pZ_eF8KCwfeRvd+X(lgds&3rw|v4Z z9Qdva_@w1i?oA0`w&D^I5$N16GD_KWa>4l%vbZNR@vqS`yeFSW&IolGnlQ$|zZGg# z=7xGegdL_2gR~qO2{SHK<}!pg@I6kK<)LM`K#a-kg(oEIWslwyVGL+95hmKuFlAL4 z5svQxoMeh$@ai(eSSCI`|$qe{TK1< zRy_N3b~}D7myhW{vV(6^>SLLBvx)FJ7 z4boK0tgjQw$*vJ3@hlc2f)oo8XFqo#odvpYj)cSff7 z<9d(LM0(7K2oEXtS1zk#8tDT?wNn*0@|emBw&oVvDqvcH~wIXu=t8Q`kM9!_jdJT|tK zY*QUjhMr9wAeas`qz*?L%?lEf-ON53d@#PRD#|6P>upM@nP}@qwv|Dt9GA)=sT}Vr Thqsl1eKn>SQVB4SqJaDd4oA4| literal 0 HcmV?d00001 diff --git a/q1-deploy-monitor/app.py b/q1-deploy-monitor/app.py index 914857d..a0f0a75 100644 --- a/q1-deploy-monitor/app.py +++ b/q1-deploy-monitor/app.py @@ -1,40 +1,48 @@ -from fastapi import FastAPI +from fastapi import FastAPI, Request import time app = FastAPI() request_count = 0 +last_response_time_ms = 0.0 + + +@app.middleware("http") +async def track_requests(request: Request, call_next): + """ + Measures the REAL processing time of every request using a middleware + that wraps the actual handler, instead of measuring time inside the + handler itself (which always returns ~0ms). + We skip counting calls to /stats itself so the dashboard polling + doesn't inflate the request counter. + """ + global request_count, last_response_time_ms + + start = time.time() + response = await call_next(request) + duration_ms = round((time.time() - start) * 1000, 2) + + if request.url.path != "/stats": + request_count += 1 + last_response_time_ms = duration_ms + + return response @app.get("/") def home(): - global request_count - request_count += 1 - - return { - "message": "Application is running" - } + return {"message": "Application is running"} @app.get("/health") def health(): - return { - "status": "UP" - } + return {"status": "UP"} @app.get("/stats") def stats(): - global request_count - - start = time.time() - - request_count += 1 - - response_time = round((time.time() - start) * 1000, 2) - return { "status": "UP", "requests": request_count, - "response_time": response_time + "response_time": last_response_time_ms } diff --git a/q1-deploy-monitor/dashboard.html b/q1-deploy-monitor/dashboard.html index aed253c..af91696 100644 --- a/q1-deploy-monitor/dashboard.html +++ b/q1-deploy-monitor/dashboard.html @@ -35,6 +35,10 @@ font-weight:bold; color:green; } + + span.down{ + color:red; + } @@ -64,25 +68,39 @@ diff --git a/q3-cicd/workflow.yml b/q3-cicd/workflow.yml index ee0e231..23c7634 100644 --- a/q3-cicd/workflow.yml +++ b/q3-cicd/workflow.yml @@ -27,14 +27,33 @@ jobs: run: | docker push registry.ghaymah.systems/my-api:${{ github.sha }} - deploy-production: + deploy-staging: needs: build runs-on: ubuntu-latest + environment: + name: staging + + steps: + - name: Deploy to Staging + run: | + echo "Deploying image ${{ github.sha }} to staging..." + # ghaymah deploy my-api-staging --image registry.ghaymah.systems/my-api:${{ github.sha }} + + deploy-production: + needs: deploy-staging + runs-on: ubuntu-latest + + # This "environment: production" line by itself does NOT block the job. + # The manual approval only happens if you also configure, on GitHub: + # Settings -> Environments -> production -> Required reviewers + # Add yourself (or a teammate) as a required reviewer there. + # Without that step, this environment tag is just a label. environment: name: production steps: - name: Deploy to Production run: | - echo "Deploying application to production..." + echo "Deploying image ${{ github.sha }} to production..." + # ghaymah deploy my-api --image registry.ghaymah.systems/my-api:${{ github.sha }} diff --git a/q4-scalability/architecture.png b/q4-scalability/architecture.png deleted file mode 100644 index ea4932c5f31f12372e8f527d0f83e0abe875df66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45463 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 d)&H>Mife2i>-n-vBk{IMe_D diff --git a/q5-mithal-monitor/Dockerfile b/q5-mithal-monitor/Dockerfile new file mode 100644 index 0000000..a829069 --- /dev/null +++ b/q5-mithal-monitor/Dockerfile @@ -0,0 +1,13 @@ +FROM python:3.12-slim + +WORKDIR /app + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . +RUN chmod +x start.sh + +EXPOSE 8080 + +CMD ["./start.sh"] diff --git a/q5-mithal-monitor/Start.sh b/q5-mithal-monitor/Start.sh new file mode 100644 index 0000000..0bd8b75 --- /dev/null +++ b/q5-mithal-monitor/Start.sh @@ -0,0 +1,11 @@ +#!/bin/bash\ +# Runs the background monitoring loop (monitor.py) and serves the +# dashboard + monitor_data.json over HTTP at the same time. + +set -e + +# Start the monitor in the background; it updates monitor_data.json every 60s +python monitor.py & + +# Serve the current directory (dashboard.html + monitor_data.json) +python -m http.server 8080 diff --git a/q5-mithal-monitor/monitor_data.json b/q5-mithal-monitor/monitor_data.json index b7d74ff..0336826 100644 --- a/q5-mithal-monitor/monitor_data.json +++ b/q5-mithal-monitor/monitor_data.json @@ -78,5 +78,1005 @@ "ssl_days_remaining": 47, "ssl_expiry": "Sep 15 13:10:47 2026 GMT", "search_latency_ms": 685.76 + }, + { + "timestamp": "2026-07-29 13:29:20", + "uptime": "UP", + "status_code": 200, + "latency_ms": 796.49, + "dns_ms": 17.73, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 702.59 + }, + { + "timestamp": "2026-07-29 13:30:22", + "uptime": "UP", + "status_code": 200, + "latency_ms": 809.36, + "dns_ms": 18.94, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 796.23 + }, + { + "timestamp": "2026-07-29 13:31:24", + "uptime": "UP", + "status_code": 200, + "latency_ms": 693.8, + "dns_ms": 19.01, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 696.29 + }, + { + "timestamp": "2026-07-29 13:32:26", + "uptime": "UP", + "status_code": 200, + "latency_ms": 1065.87, + "dns_ms": 19.99, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 672.23 + }, + { + "timestamp": "2026-07-29 13:33:28", + "uptime": "UP", + "status_code": 200, + "latency_ms": 736.77, + "dns_ms": 19.99, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 702.09 + }, + { + "timestamp": "2026-07-29 13:34:30", + "uptime": "UP", + "status_code": 200, + "latency_ms": 737.3, + "dns_ms": 17.99, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 702.44 + }, + { + "timestamp": "2026-07-29 13:35:32", + "uptime": "UP", + "status_code": 200, + "latency_ms": 711.06, + "dns_ms": 18.03, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 736.32 + }, + { + "timestamp": "2026-07-29 13:36:33", + "uptime": "UP", + "status_code": 200, + "latency_ms": 658.05, + "dns_ms": 19.51, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 710.88 + }, + { + "timestamp": "2026-07-29 13:37:36", + "uptime": "UP", + "status_code": 200, + "latency_ms": 1164.37, + "dns_ms": 35.68, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 766.8 + }, + { + "timestamp": "2026-07-29 13:38:38", + "uptime": "UP", + "status_code": 200, + "latency_ms": 655.73, + "dns_ms": 17.51, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 680.62 + }, + { + "timestamp": "2026-07-29 13:39:39", + "uptime": "UP", + "status_code": 200, + "latency_ms": 685.52, + "dns_ms": 18.46, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 785.82 + }, + { + "timestamp": "2026-07-29 13:40:41", + "uptime": "UP", + "status_code": 200, + "latency_ms": 742.43, + "dns_ms": 18.06, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 682.35 + }, + { + "timestamp": "2026-07-29 13:41:43", + "uptime": "UP", + "status_code": 200, + "latency_ms": 713.42, + "dns_ms": 18.09, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 687.09 + }, + { + "timestamp": "2026-07-29 13:42:45", + "uptime": "UP", + "status_code": 200, + "latency_ms": 702.86, + "dns_ms": 18.12, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 648.26 + }, + { + "timestamp": "2026-07-29 13:43:47", + "uptime": "UP", + "status_code": 200, + "latency_ms": 696.27, + "dns_ms": 17.36, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 735.81 + }, + { + "timestamp": "2026-07-29 13:44:49", + "uptime": "UP", + "status_code": 200, + "latency_ms": 686.58, + "dns_ms": 139.97, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 711.86 + }, + { + "timestamp": "2026-07-29 13:45:51", + "uptime": "UP", + "status_code": 200, + "latency_ms": 753.98, + "dns_ms": 17.99, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 746.27 + }, + { + "timestamp": "2026-07-29 13:46:52", + "uptime": "UP", + "status_code": 200, + "latency_ms": 747.34, + "dns_ms": 20.45, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 694.14 + }, + { + "timestamp": "2026-07-29 13:47:54", + "uptime": "UP", + "status_code": 200, + "latency_ms": 671.9, + "dns_ms": 17.89, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 687.87 + }, + { + "timestamp": "2026-07-29 13:48:56", + "uptime": "UP", + "status_code": 200, + "latency_ms": 913.91, + "dns_ms": 21.38, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 659.79 + }, + { + "timestamp": "2026-07-29 13:49:58", + "uptime": "UP", + "status_code": 200, + "latency_ms": 683.63, + "dns_ms": 18.54, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 692.84 + }, + { + "timestamp": "2026-07-29 13:51:00", + "uptime": "UP", + "status_code": 200, + "latency_ms": 688.33, + "dns_ms": 17.83, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 700.66 + }, + { + "timestamp": "2026-07-29 13:52:02", + "uptime": "UP", + "status_code": 200, + "latency_ms": 774.27, + "dns_ms": 19.76, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 854.92 + }, + { + "timestamp": "2026-07-29 13:53:03", + "uptime": "UP", + "status_code": 200, + "latency_ms": 689.02, + "dns_ms": 19.48, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 681.4 + }, + { + "timestamp": "2026-07-29 13:54:06", + "uptime": "UP", + "status_code": 200, + "latency_ms": 1442.27, + "dns_ms": 19.22, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 676.27 + }, + { + "timestamp": "2026-07-29 13:55:08", + "uptime": "UP", + "status_code": 200, + "latency_ms": 690.76, + "dns_ms": 18.06, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 694.06 + }, + { + "timestamp": "2026-07-29 13:56:10", + "uptime": "UP", + "status_code": 200, + "latency_ms": 731.26, + "dns_ms": 18.22, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 666.09 + }, + { + "timestamp": "2026-07-29 13:57:11", + "uptime": "UP", + "status_code": 200, + "latency_ms": 683.61, + "dns_ms": 17.08, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 670.91 + }, + { + "timestamp": "2026-07-29 13:58:13", + "uptime": "UP", + "status_code": 200, + "latency_ms": 701.41, + "dns_ms": 19.09, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 690.46 + }, + { + "timestamp": "2026-07-29 13:59:15", + "uptime": "UP", + "status_code": 200, + "latency_ms": 715.49, + "dns_ms": 17.84, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 655.36 + }, + { + "timestamp": "2026-07-29 14:00:17", + "uptime": "UP", + "status_code": 200, + "latency_ms": 655.69, + "dns_ms": 18.35, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 685.31 + }, + { + "timestamp": "2026-07-29 14:01:19", + "uptime": "UP", + "status_code": 200, + "latency_ms": 1569.17, + "dns_ms": 18.37, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 776.09 + }, + { + "timestamp": "2026-07-29 14:02:21", + "uptime": "UP", + "status_code": 200, + "latency_ms": 688.85, + "dns_ms": 18.66, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 697.76 + }, + { + "timestamp": "2026-07-29 14:03:23", + "uptime": "UP", + "status_code": 200, + "latency_ms": 871.11, + "dns_ms": 18.49, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 692.08 + }, + { + "timestamp": "2026-07-29 14:04:25", + "uptime": "UP", + "status_code": 200, + "latency_ms": 715.7, + "dns_ms": 18.42, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 695.7 + }, + { + "timestamp": "2026-07-29 14:05:27", + "uptime": "UP", + "status_code": 200, + "latency_ms": 779.05, + "dns_ms": 18.38, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 709.21 + }, + { + "timestamp": "2026-07-29 14:06:29", + "uptime": "UP", + "status_code": 200, + "latency_ms": 853.9, + "dns_ms": 17.51, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 677.57 + }, + { + "timestamp": "2026-07-29 14:07:30", + "uptime": "UP", + "status_code": 200, + "latency_ms": 703.27, + "dns_ms": 17.39, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 690.72 + }, + { + "timestamp": "2026-07-29 14:08:32", + "uptime": "UP", + "status_code": 200, + "latency_ms": 860.15, + "dns_ms": 18.77, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 680.07 + }, + { + "timestamp": "2026-07-29 14:09:34", + "uptime": "UP", + "status_code": 200, + "latency_ms": 947.05, + "dns_ms": 18.08, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 677.68 + }, + { + "timestamp": "2026-07-29 14:10:36", + "uptime": "UP", + "status_code": 200, + "latency_ms": 752.5, + "dns_ms": 19.24, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 700.38 + }, + { + "timestamp": "2026-07-29 14:11:39", + "uptime": "UP", + "status_code": 200, + "latency_ms": 1576.72, + "dns_ms": 19.28, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 689.53 + }, + { + "timestamp": "2026-07-29 14:12:41", + "uptime": "UP", + "status_code": 200, + "latency_ms": 816.53, + "dns_ms": 20.09, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 720.63 + }, + { + "timestamp": "2026-07-29 14:13:43", + "uptime": "UP", + "status_code": 200, + "latency_ms": 702.09, + "dns_ms": 20.07, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 677.69 + }, + { + "timestamp": "2026-07-29 14:14:44", + "uptime": "UP", + "status_code": 200, + "latency_ms": 746.56, + "dns_ms": 18.21, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 731.71 + }, + { + "timestamp": "2026-07-29 14:15:46", + "uptime": "UP", + "status_code": 200, + "latency_ms": 866.47, + "dns_ms": 20.7, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 699.85 + }, + { + "timestamp": "2026-07-29 14:16:48", + "uptime": "UP", + "status_code": 200, + "latency_ms": 692.86, + "dns_ms": 19.2, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 731.95 + }, + { + "timestamp": "2026-07-29 14:17:50", + "uptime": "UP", + "status_code": 200, + "latency_ms": 683.68, + "dns_ms": 19.22, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 704.27 + }, + { + "timestamp": "2026-07-29 14:18:52", + "uptime": "UP", + "status_code": 200, + "latency_ms": 1061.02, + "dns_ms": 19.22, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 718.16 + }, + { + "timestamp": "2026-07-29 14:19:54", + "uptime": "UP", + "status_code": 200, + "latency_ms": 736.45, + "dns_ms": 20.37, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 714.67 + }, + { + "timestamp": "2026-07-29 14:20:57", + "uptime": "UP", + "status_code": 200, + "latency_ms": 2121.53, + "dns_ms": 18.74, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 677.35 + }, + { + "timestamp": "2026-07-29 14:21:59", + "uptime": "UP", + "status_code": 200, + "latency_ms": 696.92, + "dns_ms": 19.84, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 678.32 + }, + { + "timestamp": "2026-07-29 14:23:01", + "uptime": "UP", + "status_code": 200, + "latency_ms": 748.77, + "dns_ms": 19.5, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 681.1 + }, + { + "timestamp": "2026-07-29 14:24:03", + "uptime": "UP", + "status_code": 200, + "latency_ms": 667.43, + "dns_ms": 18.06, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 693.04 + }, + { + "timestamp": "2026-07-29 14:25:04", + "uptime": "UP", + "status_code": 200, + "latency_ms": 728.73, + "dns_ms": 18.35, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 684.73 + }, + { + "timestamp": "2026-07-29 14:26:06", + "uptime": "UP", + "status_code": 200, + "latency_ms": 873.39, + "dns_ms": 19.17, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 666.09 + }, + { + "timestamp": "2026-07-29 14:27:08", + "uptime": "UP", + "status_code": 200, + "latency_ms": 686.15, + "dns_ms": 18.5, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 805.59 + }, + { + "timestamp": "2026-07-29 14:28:11", + "uptime": "UP", + "status_code": 200, + "latency_ms": 1026.35, + "dns_ms": 116.14, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 1088.1 + }, + { + "timestamp": "2026-07-29 14:29:13", + "uptime": "UP", + "status_code": 200, + "latency_ms": 786.21, + "dns_ms": 71.37, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 952.9 + }, + { + "timestamp": "2026-07-29 14:30:17", + "uptime": "UP", + "status_code": 200, + "latency_ms": 1554.83, + "dns_ms": 86.73, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 1048.98 + }, + { + "timestamp": "2026-07-29 14:31:18", + "uptime": "UP", + "status_code": 200, + "latency_ms": 819.4, + "dns_ms": 17.87, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 666.78 + }, + { + "timestamp": "2026-07-29 14:32:20", + "uptime": "UP", + "status_code": 200, + "latency_ms": 666.0, + "dns_ms": 18.86, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 705.81 + }, + { + "timestamp": "2026-07-29 14:33:22", + "uptime": "UP", + "status_code": 200, + "latency_ms": 700.31, + "dns_ms": 17.59, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 696.37 + }, + { + "timestamp": "2026-07-29 14:34:24", + "uptime": "UP", + "status_code": 200, + "latency_ms": 840.75, + "dns_ms": 19.22, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 701.29 + }, + { + "timestamp": "2026-07-29 14:35:26", + "uptime": "UP", + "status_code": 200, + "latency_ms": 748.29, + "dns_ms": 19.99, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 878.32 + }, + { + "timestamp": "2026-07-29 14:36:28", + "uptime": "UP", + "status_code": 200, + "latency_ms": 686.21, + "dns_ms": 17.91, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 701.0 + }, + { + "timestamp": "2026-07-29 14:37:29", + "uptime": "UP", + "status_code": 200, + "latency_ms": 680.49, + "dns_ms": 18.28, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 685.21 + }, + { + "timestamp": "2026-07-29 14:38:31", + "uptime": "UP", + "status_code": 200, + "latency_ms": 708.85, + "dns_ms": 18.96, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 699.8 + }, + { + "timestamp": "2026-07-29 14:39:33", + "uptime": "UP", + "status_code": 200, + "latency_ms": 677.09, + "dns_ms": 19.04, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 698.13 + }, + { + "timestamp": "2026-07-29 14:40:35", + "uptime": "UP", + "status_code": 200, + "latency_ms": 728.62, + "dns_ms": 18.71, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 726.74 + }, + { + "timestamp": "2026-07-29 14:41:37", + "uptime": "UP", + "status_code": 200, + "latency_ms": 665.49, + "dns_ms": 19.41, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 712.4 + }, + { + "timestamp": "2026-07-29 14:42:39", + "uptime": "UP", + "status_code": 200, + "latency_ms": 695.76, + "dns_ms": 18.41, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 691.33 + }, + { + "timestamp": "2026-07-29 14:43:41", + "uptime": "UP", + "status_code": 200, + "latency_ms": 706.12, + "dns_ms": 17.76, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 699.92 + }, + { + "timestamp": "2026-07-29 14:44:42", + "uptime": "UP", + "status_code": 200, + "latency_ms": 682.88, + "dns_ms": 18.85, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 702.56 + }, + { + "timestamp": "2026-07-29 14:45:44", + "uptime": "UP", + "status_code": 200, + "latency_ms": 702.09, + "dns_ms": 18.09, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 676.56 + }, + { + "timestamp": "2026-07-29 14:46:46", + "uptime": "UP", + "status_code": 200, + "latency_ms": 711.72, + "dns_ms": 25.15, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 655.21 + }, + { + "timestamp": "2026-07-29 14:47:48", + "uptime": "UP", + "status_code": 200, + "latency_ms": 706.38, + "dns_ms": 19.05, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 683.9 + }, + { + "timestamp": "2026-07-29 14:48:49", + "uptime": "UP", + "status_code": 200, + "latency_ms": 728.66, + "dns_ms": 20.74, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 690.8 + }, + { + "timestamp": "2026-07-29 14:49:51", + "uptime": "UP", + "status_code": 200, + "latency_ms": 693.39, + "dns_ms": 19.93, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 704.63 + }, + { + "timestamp": "2026-07-29 14:50:53", + "uptime": "UP", + "status_code": 200, + "latency_ms": 743.65, + "dns_ms": 18.26, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 648.65 + }, + { + "timestamp": "2026-07-29 14:51:55", + "uptime": "UP", + "status_code": 200, + "latency_ms": 708.05, + "dns_ms": 18.09, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 704.04 + }, + { + "timestamp": "2026-07-29 14:52:57", + "uptime": "UP", + "status_code": 200, + "latency_ms": 850.67, + "dns_ms": 18.12, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 707.71 + }, + { + "timestamp": "2026-07-29 14:54:03", + "uptime": "UP", + "status_code": 200, + "latency_ms": 3883.48, + "dns_ms": 120.74, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 1307.18 + }, + { + "timestamp": "2026-07-29 14:55:09", + "uptime": "UP", + "status_code": 200, + "latency_ms": 3807.11, + "dns_ms": 153.8, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 1308.85 + }, + { + "timestamp": "2026-07-29 14:56:11", + "uptime": "UP", + "status_code": 200, + "latency_ms": 720.71, + "dns_ms": 18.57, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 714.01 + }, + { + "timestamp": "2026-07-29 14:57:12", + "uptime": "UP", + "status_code": 200, + "latency_ms": 676.41, + "dns_ms": 18.24, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 656.24 + }, + { + "timestamp": "2026-07-29 14:58:14", + "uptime": "UP", + "status_code": 200, + "latency_ms": 960.72, + "dns_ms": 18.57, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 667.98 + }, + { + "timestamp": "2026-07-29 14:59:16", + "uptime": "UP", + "status_code": 200, + "latency_ms": 684.08, + "dns_ms": 19.95, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 726.08 + }, + { + "timestamp": "2026-07-29 15:00:18", + "uptime": "UP", + "status_code": 200, + "latency_ms": 726.14, + "dns_ms": 19.33, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 689.49 + }, + { + "timestamp": "2026-07-29 15:01:20", + "uptime": "UP", + "status_code": 200, + "latency_ms": 700.76, + "dns_ms": 19.22, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 680.48 + }, + { + "timestamp": "2026-07-29 15:02:22", + "uptime": "UP", + "status_code": 200, + "latency_ms": 754.22, + "dns_ms": 18.86, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 678.53 + }, + { + "timestamp": "2026-07-29 15:03:23", + "uptime": "UP", + "status_code": 200, + "latency_ms": 692.99, + "dns_ms": 18.57, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 690.92 + }, + { + "timestamp": "2026-07-29 15:04:25", + "uptime": "UP", + "status_code": 200, + "latency_ms": 683.63, + "dns_ms": 19.09, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 684.45 + }, + { + "timestamp": "2026-07-29 15:05:27", + "uptime": "UP", + "status_code": 200, + "latency_ms": 710.95, + "dns_ms": 18.54, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 680.44 + }, + { + "timestamp": "2026-07-29 15:06:29", + "uptime": "UP", + "status_code": 200, + "latency_ms": 707.22, + "dns_ms": 18.27, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 693.62 + }, + { + "timestamp": "2026-07-29 15:07:30", + "uptime": "UP", + "status_code": 200, + "latency_ms": 692.48, + "dns_ms": 18.26, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 693.3 + }, + { + "timestamp": "2026-07-29 15:08:32", + "uptime": "UP", + "status_code": 200, + "latency_ms": 689.54, + "dns_ms": 18.25, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 671.34 + }, + { + "timestamp": "2026-07-29 15:09:34", + "uptime": "UP", + "status_code": 200, + "latency_ms": 691.36, + "dns_ms": 19.3, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 743.24 + }, + { + "timestamp": "2026-07-29 15:10:37", + "uptime": "UP", + "status_code": 200, + "latency_ms": 708.47, + "dns_ms": 18.02, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 677.05 + }, + { + "timestamp": "2026-07-29 15:11:38", + "uptime": "UP", + "status_code": 200, + "latency_ms": 800.49, + "dns_ms": 18.12, + "ssl_days_remaining": 47, + "ssl_expiry": "Sep 15 13:10:47 2026 GMT", + "search_latency_ms": 679.07 } ] \ No newline at end of file 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