Skip to content

chore(profiling): opt-in native heap gotter build and skip musl (PROF-15423) - #19715

Open
vlad-scherbich wants to merge 4 commits into
vlad/native-heap-gotter-freeprobe-pr-efrom
vlad/native-heap-ci-opt-in
Open

chore(profiling): opt-in native heap gotter build and skip musl (PROF-15423)#19715
vlad-scherbich wants to merge 4 commits into
vlad/native-heap-gotter-freeprobe-pr-efrom
vlad/native-heap-ci-opt-in

Conversation

@vlad-scherbich

@vlad-scherbich vlad-scherbich commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Description

Enable building of ddtrace wheels with heap-gotter lib via GitLab. libdd_heap_gotter is never cargo-built on musllinux/Alpine, even when DD_PROFILING_NATIVE_HEAP_ENABLED=1 is set, as these platforms are incompatible with the feature.

Previous PR #19325 compiles libdd_heap_gotter into cdylib, wheel and activates the gotter's USDTs via the same flag, so in total there are two separate parts of the codebase that use the same flag in different ways.

Testing

1. Default pipeline — flag off

Push the branch without DD_PROFILING_NATIVE_HEAP_ENABLED.

Job Expect
test sdist pass — Alpine pip install from sdist succeeds
build linux (musllinux matrix, cp39–cp314) pass
upload manylinux2014_x86_64 pass

Log checks: no build_heap_gotter phase; no Built and copied heap-gotter cdylib.

Wheel check (optional):

unzip -l pywheels/*.whl | grep libdd_heap_gotter   # no matches

Verified: pipeline 131157157 — sdist + musl cp39–cp314 green, manylinux upload green, no gotter in wheels. Unrelated failures: cp315 (allow_failure), win_arm64.


2. Opt-in pipeline — flag on (manylinux)

Trigger with DD_PROFILING_NATIVE_HEAP_ENABLED=1.

GitLab UI: CI/CD → Run pipeline → branch vlad/native-heap-ci-opt-in → variable DD_PROFILING_NATIVE_HEAP_ENABLED = 1 → Run.

GitLab API:

curl --request POST \
  --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{"ref":"vlad/native-heap-ci-opt-in","variables":[{"key":"DD_PROFILING_NATIVE_HEAP_ENABLED","value":"1","variable_type":"env_var"}]}' \
  "https://gitlab.ddbuild.io/api/v4/projects/358/pipeline"
Job Expect
build linux (manylinux2014, amd64 + arm64) gotter built and packaged
upload manylinux2014_x86_64 pass
test sdist pass
profiling_native 20/20

Log checks (manylinux rows): build_heap_gotter phase; Built and copied heap-gotter cdylib: …libdd_heap_gotter….

Wheel check:

unzip -l pywheels/ddtrace-*manylinux2014_x86_64*.whl | grep libdd_heap_gotter
# expect: ddtrace/internal/datadog/profiling/.../libdd_heap_gotter*.so

Verified: pipeline 131157771libdd_heap_gotter in manylinux wheels, upload + sdist green, profiling_native 20/20.


3. Musl skip — flag on

Same pipeline as §2; inspect musllinux matrix rows (musllinux_1_2_* images).

Expect
Setup prints: WARNING: DD_PROFILING_NATIVE_HEAP_ENABLED is set but the native heap-gotter cdylib is only built on manylinux (glibc); skipping on musllinux.
No build_heap_gotter / Built and copied heap-gotter cdylib in musl job logs
Musllinux wheels contain no libdd_heap_gotter*.so
build linux musl jobs (cp39–cp314) pass

Verified: pipeline 131157771 — musl skips gotter build even with flag set.

Additional Notes

Scenario Pipeline
Flag off (default push) https://gitlab.ddbuild.io/DataDog/dd-trace-py/-/pipelines/131157157
Flag on (DD_PROFILING_NATIVE_HEAP_ENABLED=1) https://gitlab.ddbuild.io/DataDog/dd-trace-py/-/pipelines/131157771

@vlad-scherbich
vlad-scherbich requested a lite review from Copilot August 16, 2026 10:30
@vlad-scherbich

Copy link
Copy Markdown
Contributor Author

@codex review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds build-time helpers to standardize environment-flag parsing and prevents building the native heap-gotter artifact on musl-based Python builds (e.g., Alpine/musllinux), where CI/cargo builds are expected to fail.

Changes:

  • Introduces _env_truthy() for consistent parsing of boolean-ish env vars.
  • Adds is_musl_libc() detection via sysconfig build metadata.
  • Gates BUILD_NATIVE_HEAP_GOTTER on both the env flag and not is_musl_libc().

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread setup.py
Comment thread setup.py Outdated
Comment thread setup.py
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: e27c0a6288

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@datadog-official

datadog-official Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Pipelines  Tests

Unblock PR with BitsAI

⚠️ Warnings

🚦 9 Pipeline jobs failed

DataDog/apm-reliability/dd-trace-py | build linux serverless: [amd64, cp315-cp315, v113741238-d2b8243-manylinux2014_x86_64, 1]   View in Datadog   GitLab

DataDog/apm-reliability/dd-trace-py | build linux serverless: [amd64, cp315-cp315, v126532274-233089d-musllinux_1_2_x86_64, 1]   View in Datadog   GitLab

DataDog/apm-reliability/dd-trace-py | build linux: [amd64, cp315-cp315, v113741238-d2b8243-manylinux2014_x86_64]   View in Datadog   GitLab

View all 9 failed jobs.

ℹ️ Info

No other issues found (see more)

🧪 All tests passed
❄️ No new flaky tests detected

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 2566b2e | Docs | Datadog PR Page | Give us feedback!

Use _env_truthy consistently, clarify musl docstring, and warn when native
heap build is requested on musllinux.
@vlad-scherbich
vlad-scherbich force-pushed the vlad/native-heap-ci-opt-in branch from e27c0a6 to af9a77f Compare August 16, 2026 10:34
@cit-pr-commenter-54b7da

cit-pr-commenter-54b7da Bot commented Aug 16, 2026

Copy link
Copy Markdown

Codeowners resolved as

Resolved from the full PR diff against vlad/native-heap-gotter-freeprobe-pr-e using the target branch CODEOWNERS file.
CODEOWNERS team requests not listed below are not required by the current file set.

releasenotes/notes/native-heap-gotter-opt-in-wheel-build-8f3a2c1d9e4b5a07.yaml  @DataDog/apm-python
setup.py                                                                @DataDog/python-guild

@cit-pr-commenter-54b7da

cit-pr-commenter-54b7da Bot commented Aug 16, 2026

Copy link
Copy Markdown

Dependency direction analysis

⚠️ Existing dependency direction violations

There are 254 dependency direction violations that already exist on the base branch and have not been changed by this PR.

Show existing violations (showing 5 of 254 highest severity)
ddtrace.internal.tracemethods -×-> ddtrace.trace  (internal-core -> product:tracing, score=134)
ddtrace.internal.openfeature._span_enrichment -×-> ddtrace.trace  (product:openfeature -> product:tracing, score=132)
ddtrace.appsec._contrib.django -×-> ddtrace.trace  (product:appsec -> product:tracing, score=132)
ddtrace.llmobs._integrations.crewai -×-> ddtrace.trace  (product:llmobs -> product:tracing, score=132)
ddtrace.debugging._debugger -×-> ddtrace.trace  (product:debugging -> product:tracing, score=132)

To see all violations, download the layers-base.json and layers-pr.json artifacts from this CI job and run:

uv run --script scripts/import-analysis/layers.py compare layers-base.json layers-pr.json

@cit-pr-commenter-54b7da

cit-pr-commenter-54b7da Bot commented Aug 16, 2026

Copy link
Copy Markdown

Circular import analysis

⚠️ Existing circular imports

There are 5 circular imports that already exist on the base branch and have not been changed by this PR.

ddtrace.contrib.internal.pytorch._distributed -> ddtrace.contrib.internal.pytorch._rank_root -> ddtrace.contrib.internal.pytorch._distributed
ddtrace.contrib.internal.django.patch -> ddtrace.contrib.internal.django.response -> ddtrace.contrib.internal.django.patch
ddtrace.llmobs -> ddtrace.llmobs._evaluators -> ddtrace.llmobs._evaluators.format -> ddtrace.llmobs._experiment -> ddtrace.llmobs
ddtrace.errortracking._handled_exceptions.bytecode_injector -> ddtrace.errortracking._handled_exceptions.callbacks -> ddtrace.errortracking._handled_exceptions.collector -> ddtrace.errortracking._handled_exceptions.bytecode_reporting -> ddtrace.errortracking._handled_exceptions.bytecode_injector
ddtrace.appsec._asm_request_context -> ddtrace.appsec._iast._iast_request_context_base -> ddtrace.appsec._iast._iast_env -> ddtrace.appsec._iast.reporter -> ddtrace.appsec._exploit_prevention.stack_traces -> ddtrace.appsec._asm_request_context

@pr-commenter

pr-commenter Bot commented Aug 16, 2026

Copy link
Copy Markdown

Benchmarks

Benchmark execution time: 2026-08-16 13:47:00

Comparing candidate commit 2566b2e in PR branch vlad/native-heap-ci-opt-in with baseline commit 7d2117f in branch vlad/native-heap-gotter-freeprobe-pr-e.

📊 Benchmarking dashboard

Found 0 performance improvements and 6 performance regressions! Performance is the same for 616 metrics, 10 unstable metrics.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

scenario:httppropagationinject-ids_only

  • 🟥 execution_time [+2.550µs; +2.723µs] or [+12.156%; +12.982%]

scenario:iastaspectsospath-ospathbasename_aspect

  • 🟥 execution_time [+129.075µs; +138.247µs] or [+31.666%; +33.917%]

scenario:iastaspectssplit-rsplit_aspect

  • 🟥 execution_time [+13.764µs; +17.249µs] or [+9.662%; +12.108%]

scenario:span-start

  • 🟥 execution_time [+1.192ms; +1.351ms] or [+7.821%; +8.862%]

scenario:telemetryaddmetric-1-count-metric-1-times

  • 🟥 execution_time [+477.054ns; +523.946ns] or [+18.012%; +19.783%]

scenario:tracer-small

  • 🟥 execution_time [+31.406µs; +33.582µs] or [+9.597%; +10.262%]

Unstable benchmarks

These benchmarks have a confidence interval too wide to call a change; treat them as noise rather than signal.

scenario:coreapiscenario-context_with_data_listeners

  • unstable execution_time [-800.313ns; +689.474ns] or [-7.249%; +6.245%]

scenario:coreapiscenario-core_dispatch_1_listener

  • unstable execution_time [-35.656ns; +30.388ns] or [-5.815%; +4.956%]

scenario:coreapiscenario-core_dispatch_50_listeners

  • unstable execution_time [-1782.785ns; +1509.527ns] or [-10.437%; +8.837%]

scenario:coreapiscenario-core_dispatch_exception_listeners

  • unstable execution_time [-1444.387ns; +1026.837ns] or [-11.060%; +7.863%]

scenario:coreapiscenario-core_dispatch_listeners

  • unstable execution_time [-340.010ns; +313.713ns] or [-9.227%; +8.514%]

scenario:coreapiscenario-core_dispatch_no_args_listeners

  • unstable execution_time [-267.764ns; +244.755ns] or [-9.129%; +8.344%]

scenario:coreapiscenario-core_dispatch_with_results_1_listener

  • unstable execution_time [-112.207ns; +38.550ns] or [-9.466%; +3.252%]

scenario:coreapiscenario-core_dispatch_with_results_50_listeners

  • unstable execution_time [-3681.269ns; +4370.252ns] or [-9.029%; +10.718%]

scenario:coreapiscenario-core_dispatch_with_results_listeners

  • unstable execution_time [-757.810ns; +789.163ns] or [-9.192%; +9.573%]

scenario:packagesupdateimporteddependencies-import_many_stdlib_cached

  • unstable execution_time [-64.364µs; +55.821µs] or [-10.072%; +8.735%]

@vlad-scherbich vlad-scherbich changed the title fix(profiling): opt-in native heap gotter build and skip musl chore(profiling): opt-in native heap gotter build and skip musl Aug 16, 2026
@vlad-scherbich vlad-scherbich added the changelog/no-changelog A changelog entry is not required for this PR. label Aug 16, 2026
@vlad-scherbich
vlad-scherbich requested a lite review from Copilot August 16, 2026 12:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Suppressed comments (3)

setup.py:164

  • _env_truthy(\"DD_PROFILING_NATIVE_HEAP_ENABLED\") and is_musl_libc() are each evaluated twice here. Store their results in local variables (e.g., native_heap_enabled / musl) and reuse them to avoid duplicated work and keep the logic easier to follow.
# Musl is always a no-op even when the env is set (see is_musl_libc).
if _env_truthy("DD_PROFILING_NATIVE_HEAP_ENABLED") and is_musl_libc():
    print(
        "WARNING: DD_PROFILING_NATIVE_HEAP_ENABLED is set but the native heap-gotter "
        "cdylib is only built on manylinux (glibc); skipping on musllinux."
    )
BUILD_NATIVE_HEAP_GOTTER: bool = _env_truthy("DD_PROFILING_NATIVE_HEAP_ENABLED") and not is_musl_libc()

setup.py:162

  • Emitting warnings via print() from setup.py can be noisy and may not be captured consistently by build backends. Prefer routing this through a warning/logging mechanism intended for build output (e.g., warnings.warn(..., RuntimeWarning) or a setuptools/distutils logger), ideally to stderr.
    print(
        "WARNING: DD_PROFILING_NATIVE_HEAP_ENABLED is set but the native heap-gotter "
        "cdylib is only built on manylinux (glibc); skipping on musllinux."
    )

setup.py:170

  • Now that _env_truthy() exists, this line duplicates the prior boolean-parsing pattern. Consider switching SERVERLESS_BUILD to _env_truthy(\"DD_SERVERLESS_BUILD\") for consistency and to keep the accepted truthy values centralized.
SERVERLESS_BUILD = os.getenv("DD_SERVERLESS_BUILD", "0").lower() in ("1", "yes", "on", "true")

@vlad-scherbich
vlad-scherbich force-pushed the vlad/native-heap-ci-opt-in branch from f4338f9 to a86da7a Compare August 16, 2026 13:01
@vlad-scherbich
vlad-scherbich requested a lite review from Copilot August 16, 2026 13:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Suppressed comments (5)

setup.py:135

  • _env_truthy() will treat values with leading/trailing whitespace as false (e.g., DD_FOO='true '), which can be surprising when env vars come from CI or shell tooling. Consider normalizing with .strip().lower() before membership checking.
def _env_truthy(name: str, default: str = "0") -> bool:
    return os.getenv(name, default).lower() in ("1", "yes", "on", "true")

setup.py:164

  • is_musl_libc() is called twice; it would be simpler and avoid repeated sysconfig.get_config_var() lookups to compute it once (e.g., musl = is_musl_libc()) and reuse it for both the warning branch and BUILD_NATIVE_HEAP_GOTTER.
if _env_truthy("DD_PROFILING_NATIVE_HEAP_ENABLED") and is_musl_libc():

setup.py:164

  • is_musl_libc() is called twice; it would be simpler and avoid repeated sysconfig.get_config_var() lookups to compute it once (e.g., musl = is_musl_libc()) and reuse it for both the warning branch and BUILD_NATIVE_HEAP_GOTTER.
BUILD_NATIVE_HEAP_GOTTER: bool = _env_truthy("DD_PROFILING_NATIVE_HEAP_ENABLED") and not is_musl_libc()

setup.py:161

  • Emitting a warning via print() in setup.py can be noisy and hard to filter in build logs. Prefer warnings.warn(...) (or distutils.log.warn(...) if this repo uses distutils logging elsewhere) so users can control visibility and tooling can classify it properly.
    print(
        "WARNING: DD_PROFILING_NATIVE_HEAP_ENABLED is set but the native heap-gotter "
        "cdylib is only built on manylinux (glibc); skipping on musllinux."
    )

setup.py:167

  • This assignment drops the explicit : bool type annotation that existed previously for the same flag, while BUILD_NATIVE_HEAP_GOTTER remains annotated. Consider keeping BUILD_NATIVE_HEAP_GOTTER_TEST_SUPPORT: bool = ... for consistent typing among build flags.
BUILD_NATIVE_HEAP_GOTTER_TEST_SUPPORT = _env_truthy("DD_PROFILING_NATIVE_HEAP_TEST_SUPPORT")

@vlad-scherbich vlad-scherbich changed the title chore(profiling): opt-in native heap gotter build and skip musl chore(profiling): opt-in native heap gotter build and skip musl (PROF-15423) Aug 16, 2026
Document setup.py gate: gotter cdylib ships only when
DD_PROFILING_NATIVE_HEAP_ENABLED=1 at build time; musl always skips.
@vlad-scherbich
vlad-scherbich requested a lite review from Copilot August 16, 2026 20:09
@vlad-scherbich
vlad-scherbich marked this pull request as ready for review August 16, 2026 20:09
@vlad-scherbich
vlad-scherbich requested review from a team as code owners August 16, 2026 20:09
@vlad-scherbich
vlad-scherbich requested review from gnufede and removed request for a team August 16, 2026 20:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (2)

setup.py:164

  • Calling is_musl_libc() twice duplicates the detection work and can also lead to inconsistent outcomes if sysconfig values differ across calls (e.g., due to environment changes during setup execution). Compute the musl flag once (e.g., musl = is_musl_libc()) and reuse it for both the warning and BUILD_NATIVE_HEAP_GOTTER assignment.
# Musl is always a no-op even when the env is set (see is_musl_libc).
if _env_truthy("DD_PROFILING_NATIVE_HEAP_ENABLED") and is_musl_libc():
    print(
        "WARNING: DD_PROFILING_NATIVE_HEAP_ENABLED is set but the native heap-gotter "
        "cdylib is only built on manylinux (glibc); skipping on musllinux."
    )
BUILD_NATIVE_HEAP_GOTTER: bool = _env_truthy("DD_PROFILING_NATIVE_HEAP_ENABLED") and not is_musl_libc()

setup.py:162

  • Using print() in setup.py can be swallowed or poorly formatted depending on the build frontend (pip/build/PEP 517). Prefer emitting a warning via warnings.warn(..., RuntimeWarning) (or the project’s existing logging/warning mechanism if one exists) so build logs consistently capture it and tooling can surface it appropriately.
    print(
        "WARNING: DD_PROFILING_NATIVE_HEAP_ENABLED is set but the native heap-gotter "
        "cdylib is only built on manylinux (glibc); skipping on musllinux."
    )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog/no-changelog A changelog entry is not required for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants