Skip to content

Commit b792769

Browse files
feat(python): add core 3.14/3.15 gate scenarios (lock, exceptions, async_gen)
Add six paired scenarios for the migration gate with lock-release and lock name labels plus exception type labels. Stacks on gate-infra (PR-0).
1 parent 3c9e15e commit b792769

26 files changed

Lines changed: 399 additions & 30 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ Both use [dd-octo-sts](https://github.com/DataDog/dd-octo-sts-action) (`dd-trace
7777
**Inputs:**
7878

7979
- `dd_trace_py_commit_sha` — commit to test (required)
80-
- `test_scenarios` — regexp passed to `TEST_SCENARIOS` (see the [3.14/3.15 migration gate index](scenarios/python_downstream_gate/README.md); the downstream workflow default alone is `python.*`)
80+
- `test_scenarios` — regexp passed to `TEST_SCENARIOS` (dd-trace-py passes the [6-scenario 3.14/3.15 migration gate](scenarios/python_downstream_gate/README.md); the downstream workflow default alone is `python.*`)
8181

8282
## Creating new tests
8383

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
ARG BASE_IMAGE="prof-python-3.14"
2+
FROM $BASE_IMAGE
3+
4+
RUN pip install ddtrace
5+
6+
COPY ./scenarios/python_async_gen_3.14/main.py /app/main.py
7+
WORKDIR /app
8+
9+
ENV EXECUTION_TIME_SEC=8
10+
ENV _DD_PROFILING_STACK_ADAPTIVE_SAMPLING_ENABLED=0
11+
ENV DD_PROFILING_ENABLED=true
12+
13+
CMD ddtrace-run python main.py
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"test_name": "python_async_gen_3.14",
3+
"stacks": [
4+
{
5+
"profile-type": "wall-time",
6+
"stack-content": [
7+
{
8+
"regular_expression": ".*async_gen_work.*",
9+
"percent": 50,
10+
"error_margin": 100
11+
}
12+
]
13+
}
14+
],
15+
"scale_by_duration": false
16+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import asyncio
2+
import os
3+
4+
5+
async def async_gen_work() -> None:
6+
async def ticker() -> object:
7+
for i in range(1_000_000):
8+
yield i
9+
if i % 10_000 == 0:
10+
await asyncio.sleep(0)
11+
12+
async for _ in ticker():
13+
pass
14+
15+
16+
async def main() -> None:
17+
await asyncio.sleep(0.5)
18+
execution_time_sec = float(os.environ.get("EXECUTION_TIME_SEC", "8"))
19+
await asyncio.wait_for(async_gen_work(), timeout=execution_time_sec)
20+
21+
22+
if __name__ == "__main__":
23+
asyncio.run(main())
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ddtrace
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
ARG BASE_IMAGE="prof-python-3.15"
2+
FROM $BASE_IMAGE
3+
4+
COPY ./scenarios/python_async_gen_3.15/main.py /app/main.py
5+
WORKDIR /app
6+
7+
ENV EXECUTION_TIME_SEC=8
8+
ENV _DD_PROFILING_STACK_ADAPTIVE_SAMPLING_ENABLED=0
9+
ENV DD_PROFILING_ENABLED=true
10+
11+
CMD ddtrace-run python main.py
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"test_name": "python_async_gen_3.15",
3+
"stacks": [
4+
{
5+
"profile-type": "wall-time",
6+
"stack-content": [
7+
{
8+
"regular_expression": ".*async_gen_work.*",
9+
"percent": 50,
10+
"error_margin": 100
11+
}
12+
]
13+
}
14+
],
15+
"scale_by_duration": false
16+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import asyncio
2+
import os
3+
4+
5+
async def async_gen_work() -> None:
6+
async def ticker() -> object:
7+
for i in range(1_000_000):
8+
yield i
9+
if i % 10_000 == 0:
10+
await asyncio.sleep(0)
11+
12+
async for _ in ticker():
13+
pass
14+
15+
16+
async def main() -> None:
17+
await asyncio.sleep(0.5)
18+
execution_time_sec = float(os.environ.get("EXECUTION_TIME_SEC", "8"))
19+
await asyncio.wait_for(async_gen_work(), timeout=execution_time_sec)
20+
21+
22+
if __name__ == "__main__":
23+
asyncio.run(main())
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ddtrace
Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,50 @@
11
# Python downstream gate (dd-trace-py)
22

3-
Paired **3.14 (baseline)** and **3.15 (candidate)** prof-correctness scenarios
4-
exercise the Python profiling stack for the 3.14 → 3.15 migration. They are the
5-
intended default set when dd-trace-py triggers downstream CI on profiling changes.
6-
7-
**Scenarios land in follow-up PRs** (core families first, then feature-specific
8-
pairs). This directory is an index only — not a runnable scenario.
3+
Six prof-correctness scenarios exercise the profiling stack on **3.14
4+
(baseline)** and **3.15 (candidate)** for the same workloads. They are the
5+
default set when dd-trace-py triggers downstream CI on profiling changes.
96

107
## Scenarios
118

12-
| Family | 3.14 (baseline) | 3.15 (candidate) | PR |
13-
|--------|-----------------|---------------------|-----|
14-
| _(pending)_ ||| Core scenarios in follow-up PRs |
9+
| Family | 3.14 (baseline) | 3.15 (candidate) |
10+
|--------|-------------------|------------------|
11+
| exceptions | `python_exceptions_3.14` | `python_exceptions_3.15` |
12+
| async-gen | `python_async_gen_3.14` | `python_async_gen_3.15` |
13+
| lock | `python_lock_3.14` | `python_lock_3.15` |
14+
15+
## Profiler coverage
16+
17+
| Family | Profile type asserted | Collectors / setup |
18+
|--------|----------------------|--------------------|
19+
| exceptions | `exception-samples` + `exception type` | Exception profiler |
20+
| async-gen | `wall-time` | Full profiler via `ddtrace-run`; asyncio async-generator workload |
21+
| lock | `lock-acquire` + `lock-release` + `lock name` | Lock profiler; threaded lock churn |
22+
23+
Feature-specific pairs (mem_domain, live_heap) and extended coverage (cpu, alloc,
24+
asyncio, …) land in follow-up PRs.
1525

1626
## Default downstream regexp
1727

18-
Once scenarios are added, dd-trace-py should pass an explicit regexp (not the
19-
downstream workflow default of `python.*`). The regexp grows as families merge;
20-
see each PR for the current value.
28+
```
29+
python_(exceptions|async_gen|lock)_3\.(14|15)
30+
```
2131

2232
Override via `workflow_dispatch``test_scenarios`, or when triggering
2333
[`downstream-python.yml`](../../.github/workflows/downstream-python.yml) manually.
2434

2535
## Wheel install
2636

27-
Every scenario builds against a **dd-trace-py wheel** via `DDTRACE_INSTALL_URL`
28-
(as `downstream-python.yml` does:
29-
`https://dd-trace-py-builds.s3.amazonaws.com/<sha>/install.sh`), pre-installed in
30-
the base image.
31-
32-
- **All `*_3.15` folders** — PyPI wheels may not be published for 3.15 yet;
33-
excluded from prof-correctness `main` CI (see `test_scenarios_exclude` in
34-
[`.github/workflows/ci.yml`](../../.github/workflows/ci.yml)).
35-
- **Wheel-only 3.14 folders** — scenarios that depend on unreleased ddtrace
36-
features are also excluded from `main` CI until the feature ships.
37+
- **All `*_3.15` folders** use `DDTRACE_INSTALL_URL` (excluded from `main` CI).
38+
- **3.14 folders** run on prof-correctness `main` CI against PyPI ddtrace.
3739

3840
## Local run
3941

4042
```sh
4143
export DDTRACE_INSTALL_URL="https://dd-trace-py-builds.s3.amazonaws.com/<commit-sha>/install.sh"
42-
TEST_SCENARIOS='<gate-regexp>' go test -v -run TestScenarios
44+
TEST_SCENARIOS='python_(exceptions|async_gen|lock)_3\.(14|15)' go test -v -run TestScenarios
4345
```
4446

45-
## Gate lifecycle
46-
47-
This gate tests the **migration delta** (3.14 → 3.15). It is time-boxed: retire
48-
the paired 14v15 framing at 3.15 GA and fold workloads into steady-state
49-
prof-correctness on {oldest, newest} supported Python versions.
50-
5147
## Further reading
5248

49+
- Gate infra: PR stacking from `vlad/gate-infra`
5350
- prof-correctness downstream wiring: [README](../../README.md#downstream-from-dd-trace-py)

0 commit comments

Comments
 (0)