From 42e48e5f4fea32aceba6a5de2685af9932404e14 Mon Sep 17 00:00:00 2001 From: Thomas Kowalski Date: Fri, 26 Dec 2025 09:52:33 +0100 Subject: [PATCH] [python_uwsgi] Initial commit --- scenarios/python_uwsgi_3.11/Dockerfile | 25 +++++++++++ scenarios/python_uwsgi_3.11/app.py | 44 +++++++++++++++++++ .../python_uwsgi_3.11/expected_profile.json | 37 ++++++++++++++++ scenarios/python_uwsgi_3.11/requirements.txt | 3 ++ scenarios/python_uwsgi_3.11/uwsgi.ini | 17 +++++++ 5 files changed, 126 insertions(+) create mode 100644 scenarios/python_uwsgi_3.11/Dockerfile create mode 100644 scenarios/python_uwsgi_3.11/app.py create mode 100644 scenarios/python_uwsgi_3.11/expected_profile.json create mode 100644 scenarios/python_uwsgi_3.11/requirements.txt create mode 100644 scenarios/python_uwsgi_3.11/uwsgi.ini diff --git a/scenarios/python_uwsgi_3.11/Dockerfile b/scenarios/python_uwsgi_3.11/Dockerfile new file mode 100644 index 0000000..9f42123 --- /dev/null +++ b/scenarios/python_uwsgi_3.11/Dockerfile @@ -0,0 +1,25 @@ +ARG BASE_IMAGE="prof-python-3.11" +FROM $BASE_IMAGE + +# Copy the Python target into the container +COPY ./scenarios/python_uwsgi_3.11/requirements.txt /app/ +RUN chmod 644 /app/* + +# Set the working directory to the location of the program +WORKDIR /app + +RUN pip install -r requirements.txt + +COPY ./scenarios/python_uwsgi_3.11/app.py /app/ +COPY ./scenarios/python_uwsgi_3.11/uwsgi.ini /app/ + +ENV DD_TRACE_ENABLED=false +ENV DD_PROFILING_ENABLED=true +ENV DD_TRACE_DEBUG=false +ENV DD_PROFILING_UPLOAD_INTERVAL=3 +ENV _DD_PROFILING_STACK_ADAPTIVE_SAMPLING_ENABLED=0 +ENV DD_PROFILING_OUTPUT_PPROF="/app/data/profiles" +ENV EXECUTION_TIME_SEC=10 + +# Run the program when the container starts +CMD ["uwsgi", "--ini", "uwsgi.ini"] diff --git a/scenarios/python_uwsgi_3.11/app.py b/scenarios/python_uwsgi_3.11/app.py new file mode 100644 index 0000000..1ff5ac8 --- /dev/null +++ b/scenarios/python_uwsgi_3.11/app.py @@ -0,0 +1,44 @@ +import os +import signal +import time +from collections.abc import Callable +from threading import Thread + +import requests +import uwsgi # pyright: ignore[reportMissingModuleSource] + + +def _make_requests() -> None: + run_time = int(os.environ.get("EXECUTION_TIME_SEC", 10)) + + start = time.monotonic() + while time.monotonic() - start < run_time: + try: + print(f"Requester PID: {os.getpid()} requesting") + requests.get("http://localhost:8000", timeout=1) + except Exception as e: # noqa: PERF203,BLE001 + print(e) + + time.sleep(1.0) + + # Ask the master process to exit + try: + os.kill(uwsgi.masterpid(), signal.SIGINT) + finally: + pass + + +def compute_big_number() -> int: + x = 0 + for i in range(1_000_000): + x *= i + return x + + +def application(environ: dict, start_response: Callable) -> list[bytes]: # noqa: ARG001 # pyright: ignore[reportUnusedParameter] + x = compute_big_number() + start_response("200 OK", [("Content-Type", "text/plain")]) + return [f"Hello, World! {x}".encode()] + + +Thread(target=_make_requests, daemon=True, name="Requester").start() diff --git a/scenarios/python_uwsgi_3.11/expected_profile.json b/scenarios/python_uwsgi_3.11/expected_profile.json new file mode 100644 index 0000000..3ff948a --- /dev/null +++ b/scenarios/python_uwsgi_3.11/expected_profile.json @@ -0,0 +1,37 @@ +{ + "test_name": "python_uwsgi_3.11", + "scale_by_duration": true, + "pprof-regex": "", + "stacks": [ + { + "profile-type": "wall-time", + "pprof-regex": "", + "stack-content": [ + { + "regular_expression": ".*_make_requests.*", + "percent": 33, + "error_margin": 5, + "labels": [ + { + "key": "thread name", + "values": [ + "Requester" + ] + } + ] + } + ] + }, + { + "profile-type": "wall-time", + "pprof-regex": "", + "stack-content": [ + { + "regular_expression": ".*application;compute_big_number.*", + "percent": 30, + "error_margin": 7 + } + ] + } + ] +} \ No newline at end of file diff --git a/scenarios/python_uwsgi_3.11/requirements.txt b/scenarios/python_uwsgi_3.11/requirements.txt new file mode 100644 index 0000000..36088c1 --- /dev/null +++ b/scenarios/python_uwsgi_3.11/requirements.txt @@ -0,0 +1,3 @@ +ddtrace +requests +uwsgi diff --git a/scenarios/python_uwsgi_3.11/uwsgi.ini b/scenarios/python_uwsgi_3.11/uwsgi.ini new file mode 100644 index 0000000..d1d977f --- /dev/null +++ b/scenarios/python_uwsgi_3.11/uwsgi.ini @@ -0,0 +1,17 @@ +[uwsgi] +worker-reload-mercy = 3 +harakiri = 0 +harakiri-graceful-timeout = 3 +py-call-osafterfork = true + +module = app:application +http = 127.0.0.1:8000 + +master = true +processes = 3 + +;; ddtrace required options +enable-threads = 1 +lazy-apps = 1 +skip-atexit = 1 ; For uwsgi<2.0.30 +import=ddtrace.bootstrap.sitecustomize \ No newline at end of file