Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions scenarios/python_uwsgi_3.11/Dockerfile
Original file line number Diff line number Diff line change
@@ -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"]
44 changes: 44 additions & 0 deletions scenarios/python_uwsgi_3.11/app.py
Original file line number Diff line number Diff line change
@@ -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()
37 changes: 37 additions & 0 deletions scenarios/python_uwsgi_3.11/expected_profile.json
Original file line number Diff line number Diff line change
@@ -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
}
]
}
]
}
3 changes: 3 additions & 0 deletions scenarios/python_uwsgi_3.11/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ddtrace
requests
uwsgi
17 changes: 17 additions & 0 deletions scenarios/python_uwsgi_3.11/uwsgi.ini
Original file line number Diff line number Diff line change
@@ -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