From cde554c981002a2006f8a091256cd922680119e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Bu=C3=9Fmann?= Date: Sun, 15 Feb 2026 16:53:17 +0100 Subject: [PATCH] . --- .dockerignore | 19 ++++++++++++++ Dockerfile | 36 ++++++++++++++++++++++++++ analysis.py | 67 ------------------------------------------------ requirements.txt | 55 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 67 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile delete mode 100644 analysis.py create mode 100644 requirements.txt diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..8f0f6df --- /dev/null +++ b/.dockerignore @@ -0,0 +1,19 @@ +__pycache__ +*.pyc +*.pyo +*.pyd +.Python +.env +.venv +.git +.gitignore +*.sqlite3 +*.db +analysis.py +db.py +pyproject.toml +README.md +run_speedtest.py +uv.lock +.dockerignore +.python-version diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..9fdf02e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,36 @@ +# Use a lightweight Python base image +FROM python:3.13-slim + +# Set environment variables to prevent Python from writing pyc files +# and to flush stdout/stderr immediately (useful for docker logs) +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + +# Set the working directory +WORKDIR /app + +RUN apt-get update && \ + apt-get install -y git && \ + rm -rf /var/lib/apt/lists/* + +# Install dependencies first (for better caching) +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Copy the rest of the application code +COPY . . + +# Create a directory for the database mount (optional but good for clarity) +RUN mkdir -p /data + +# Default environment variable for the database path inside the container +ENV DB_PATH="/data/speedtest.db" +ENV PORT=5000 + +# Expose the port the app runs on +EXPOSE 5000 + +# Run using Gunicorn +# -b 0.0.0.0:5000: Bind to all interfaces on port 5000 +# --access-logfile -: Log access to stdout +CMD ["gunicorn", "--workers", "1", "--bind", "0.0.0.0:5000", "--access-logfile", "-", "app:app"] diff --git a/analysis.py b/analysis.py deleted file mode 100644 index 7c19eed..0000000 --- a/analysis.py +++ /dev/null @@ -1,67 +0,0 @@ -import sqlite3 -import os -from datetime import datetime -import pytz -import time - -from config import DB_PATH - -def get_conn() -> sqlite3.Connection: - uri = f"file:{os.path.abspath(DB_PATH)}?cache=shared" - conn = sqlite3.connect(uri, uri=True, check_same_thread=False) - conn.row_factory = sqlite3.Row - conn.execute("PRAGMA journal_mode=WAL;") - conn.execute("PRAGMA synchronous=NORMAL;") - conn.execute("PRAGMA temp_store=MEMORY;") - conn.execute("PRAGMA cache_size=-20000;") # ~20MB cache - return conn - -CONN = get_conn() - -# ---------------------- Utilities ---------------------- - -def ts_to_iso(ts: float | int | str) -> str: - try: - t = float(ts) - except Exception: - return str(ts) - return datetime.fromtimestamp(t, tz=pytz.timezone("Europe/Berlin")).isoformat() - -# ---------------------- API Endpoints ---------------------- - -def api_series(q_from: float, q_to: float): - params = [] - where = [] - if q_from is not None: - where.append("timestamp >= ?") - params.append(q_from) - if q_to is not None: - where.append("timestamp <= ?") - params.append(q_to) - where_sql = ("WHERE " + " AND ".join(where)) if where else "" - - sql = ( - f"SELECT timestamp, down_90th, up_90th FROM speed_tests {where_sql} " - "ORDER BY timestamp ASC;" - ) - - rows = [] - for i, r in enumerate(CONN.execute(sql, params)): - rows.append({ - "t": float(r["timestamp"]), - "t_iso": ts_to_iso(r["timestamp"]), - "down_90th": None if r["down_90th"] is None else float(r["down_90th"]), - "up_90th": None if r["up_90th"] is None else float(r["up_90th"]), - }) - - return rows - -rows = api_series(1756220400, time.time()) - -does_not_work = 0 - -for r in rows: - if r["down_90th"] is None or r["up_90th"] is None: - does_not_work += 1 - -print(f"Working percentage: {100 - (does_not_work / len(rows))*100}% ({does_not_work}/{len(rows)})") diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..bea1584 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,55 @@ +# This file was autogenerated by uv via the following command: +# uv export --format requirements-txt -o requirements.txt --no-hashes +blinker==1.9.0 + # via flask +certifi==2025.11.12 + # via requests +charset-normalizer==3.4.4 + # via requests +click==8.3.1 + # via flask +cloudflarepycli @ git+https://github.com/cato447/cloudflarepycli@26477fb5511839648a774f1685426925b5b44311 + # via speed-logger +colorama==0.4.6 ; sys_platform == 'win32' + # via click +flask==3.1.2 + # via speed-logger +getmac==0.9.5 + # via speed-logger +gunicorn==23.0.0 + # via speed-logger +idna==3.11 + # via requests +itsdangerous==2.2.0 + # via flask +jinja2==3.1.6 + # via flask +markupsafe==3.0.3 + # via + # flask + # jinja2 + # werkzeug +numpy==2.4.0 + # via pandas +packaging==25.0 + # via gunicorn +pandas==2.3.3 + # via speed-logger +prometheus-client==0.23.1 + # via speed-logger +python-dateutil==2.9.0.post0 + # via pandas +pytz==2025.2 + # via + # pandas + # speed-logger +requests==2.32.5 + # via cloudflarepycli +six==1.17.0 + # via python-dateutil +tzdata==2025.3 + # via pandas +urllib3==2.6.2 + # via requests +werkzeug==3.1.4 + # via flask