- Created a GitHub Actions workflow for CI/CD to deploy to Ghyamah, including testing, building, and pushing Docker images. - Added architecture design document for handling 15,000 requests per second, detailing system components, capacity planning, and cold start strategies. - Introduced a Python-based uptime/latency/SSL monitor with a static dashboard, utilizing standard libraries only. - Included Dockerfile and entrypoint script for the monitoring application, ensuring it runs as a non-root user and handles process management. - Added a .dockerignore file to exclude unnecessary files from the Docker build context. - Created an HTML dashboard for visualizing monitoring metrics, including uptime, latency, and SSL certificate status.
80 أسطر
3.4 KiB
Markdown
80 أسطر
3.4 KiB
Markdown
# mithal-space-monitor
|
|
|
|
A lightweight, stdlib-only uptime/latency/SSL monitor with a single-page
|
|
Chart.js dashboard, packaged into one container.
|
|
|
|
## What's inside
|
|
|
|
| File | Purpose |
|
|
|---|---|
|
|
| `monitor.py` | Standard-library-only Python script. Every `CHECK_INTERVAL` seconds it checks DNS resolution time, HTTP status + latency, search-endpoint latency, and SSL cert expiry, then writes a rolling `RETENTION_HOURS` window to a JSON file. |
|
|
| `index.html` | Single-page dashboard (HTML/CSS/JS + Chart.js via CDN). Polls the JSON file every 30s and renders 24h uptime %, a 60-minute latency line chart, SSL expiry, and a table of the last 10 checks. |
|
|
| `entrypoint.sh` | Starts `monitor.py` and `python -m http.server` side by side, forwards signals, and exits the container if either process dies (so the orchestrator restarts it). |
|
|
| `Dockerfile` | `python:3.12-alpine` base, non-root user, healthcheck, no external Python deps. |
|
|
|
|
## Configuration (environment variables)
|
|
|
|
| Variable | Default | Description |
|
|
|---|---|---|
|
|
| `TARGET_URL` | `https://mithal.space` | URL to monitor |
|
|
| `SEARCH_PATH` | `/search?q=test` | Path appended to the target's origin for the search-latency check |
|
|
| `CHECK_INTERVAL` | `60` | Seconds between checks |
|
|
| `RETENTION_HOURS` | `24` | Rolling window kept in the JSON log |
|
|
| `REQUEST_TIMEOUT` | `10` | Per-request timeout (seconds) |
|
|
| `PORT` | `8080` | Dashboard HTTP server port |
|
|
|
|
## Build & run locally
|
|
|
|
```bash
|
|
docker build -t mithal-space-monitor .
|
|
|
|
docker run -d \
|
|
--name mithal-monitor \
|
|
-p 8080:8080 \
|
|
-e TARGET_URL="https://mithal.space" \
|
|
-e SEARCH_PATH="/search?q=test" \
|
|
-v mithal_monitor_data:/app/data \
|
|
mithal-space-monitor
|
|
|
|
# open http://localhost:8080
|
|
```
|
|
|
|
The `-v mithal_monitor_data:/app/data` volume is optional but recommended so
|
|
your 24h history survives a container restart/redeploy.
|
|
|
|
## Push to a registry
|
|
|
|
```bash
|
|
docker tag mithal-space-monitor registry.example.com/yourorg/mithal-space-monitor:latest
|
|
docker push registry.example.com/yourorg/mithal-space-monitor:latest
|
|
```
|
|
|
|
## Deploy
|
|
|
|
This image is a single process group exposing one HTTP port, so it runs
|
|
as-is on most container platforms:
|
|
|
|
- **Cloud Run / Container Apps / Fly.io**: deploy the image, set `PORT`
|
|
to match the platform's expected port (Cloud Run injects `PORT`
|
|
automatically - the entrypoint already respects it), mount a persistent
|
|
volume if the platform supports one (otherwise history resets on redeploy,
|
|
which is fine - it just rebuilds over the next `RETENTION_HOURS`).
|
|
- **Kubernetes**: run as a `Deployment` with 1 replica, a `Service` of type
|
|
`ClusterIP`/`LoadBalancer`, and optionally a `PersistentVolumeClaim`
|
|
mounted at `/app/data`. The built-in `HEALTHCHECK` maps naturally to a
|
|
liveness probe on `GET /`.
|
|
- **Plain VM / docker-compose**: use the `docker run` command above behind
|
|
your existing reverse proxy / TLS terminator.
|
|
|
|
## Notes & extension points
|
|
|
|
- Everything in `monitor.py` uses only the Python standard library
|
|
(`urllib`, `socket`, `ssl`, `json`) - no `pip install` step, no
|
|
dependency surface in the image.
|
|
- Data is written atomically (`write → temp file → os.replace`) so the
|
|
dashboard never reads a half-written JSON file.
|
|
- To monitor multiple targets, run one container per target (each with its
|
|
own `TARGET_URL`/port), or extend `monitor.py` to loop over a list of
|
|
targets and extend `index.html` with a target selector.
|
|
- Add basic auth / IP allowlisting at your reverse proxy if the dashboard
|
|
shouldn't be public. |