build(profiling): add native heap-gotter cdylib build (PROF-15750) - #19078
Conversation
Circular import analysis
|
Codeowners resolved asResolved from the full PR diff against No remaining files require a CODEOWNERS review. |
🎉 All green!🧪 All tests passed 🔄 Datadog auto-retried 1 job - 1 passed on retry 🔗 Commit SHA: a7e3bbb | Docs | Datadog PR Page | Give us feedback! |
BenchmarksBenchmark execution time: 2026-08-12 13:54:22 Comparing candidate commit a7e3bbb in PR branch Found 0 performance improvements and 8 performance regressions! Performance is the same for 613 metrics, 9 unstable metrics. scenario:httppropagationextract-datadog_tracecontext_tracestate_not_propagated_on_trace_id_no_match
scenario:httppropagationinject-ids_only
scenario:iastaspects-lstrip_aspect
scenario:iastaspects-translate_aspect
scenario:iastaspectsospath-ospathbasename_aspect
scenario:span-start
scenario:telemetryaddmetric-1-count-metric-1-times
scenario:telemetryaddmetric-record-1000-metrics
|
bbd57cb to
852359d
Compare
683165f to
b8309ae
Compare
|
@codex review plz ty |
There was a problem hiding this comment.
Pull request overview
Adds the first (build-only) component of the native heap profiling stack by introducing a standalone Rust cdylib (“heap gotter”) that wraps the published libdd-profiling-heap-gotter crate and stages the resulting shared library into the Python wheel when opt-in build flags are enabled.
Changes:
- Introduces a new Rust
cdylibcrate (src/native_heap_gotter) that exports a small stable C ABI for installation/status/testing hooks. - Extends
setup.pyto optionally build and packagelibdd_heap_gotter<EXT_SUFFIX>.sowhenDD_PROFILING_NATIVE_HEAP_BUILD=1on Linux x86_64. - Ignores the new crate’s Rust build artifacts in
.gitignore.
Reviewed changes
Copilot reviewed 3 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/native_heap_gotter/lib.rs | Exposes stable extern "C" entry points wrapping the upstream Rust API. |
| src/native_heap_gotter/Cargo.toml | Defines the wrapper cdylib crate and pins libdd-profiling-heap-gotter = 1.0.0 with default-features = false. |
| src/native_heap_gotter/Cargo.lock | Locks Rust dependencies for reproducible builds of the new crate. |
| setup.py | Adds opt-in build flag, builds/stages the cdylib, and includes it in package_data when enabled. |
| .gitignore | Ignores src/native_heap_gotter/target* artifacts. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b8309ae723
ℹ️ 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".
|
@codex re-review |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 9 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
setup.py:1058
cargo buildfor the heap-gotter crate should use--lockedto guarantee the checked-inCargo.lockis honored and to prevent build-time lockfile updates/drift (especially important for reproducible wheel builds).
cargo_cmd = [
"cargo",
"build",
"--release",
"--manifest-path",
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7ddaa1702f
ℹ️ 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".
b91736e to
a7d41a8
Compare
6f9a607 to
5375271
Compare
emmettbutler
left a comment
There was a problem hiding this comment.
Seems ok. Main concern is binary size, which it sounds like is limited by the opt-in nature of this feature. Hopefully the affected artifact is having its size checked somewhere in CI.
Agreed on the concern. For now, wheels stay unchanged, unless |
Add a build-only Rust cdylib (src/native_heap_gotter) that wraps the published crates.io crate libdd-profiling-heap-gotter 1.0.0 and exports a small C ABI (ddtrace_heap_gotter_install / _is_installed / _test_hook_hits). When built (DD_PROFILING_NATIVE_HEAP_BUILD=1, Linux 64-bit) the wheel ships libdd_heap_gotter*.so with a patchelf-set soname; the profiler does not load it yet, so this PR is inert. Allocation-only surface (ddheap:alloc USDT); default-features=false keeps live-heap opt-in and off.
- setup.py: locate the heap-gotter cdylib from cargo JSON artifact output instead of a hard-coded target/release path, so CARGO_TARGET_DIR and --target-dir/--target in DD_CARGO_ARGS are honored. - setup.py: correct the opt-in build rationale now that the gotter is a crates.io version pin (not a moving libdatadog main SHA). - lib.rs: ddtrace_heap_gotter_install() returns the actual install result so a no-op install (no symbols resolved / sampling disabled) is not reported as success while remaining idempotent across fork(). - MANIFEST.in: prune src/native_heap_gotter/target* from sdists. - CI: run cargo fmt/clippy/test on the new crate in "rust ci", trigger profiling_native on its changes, and scan it in the coverage guard.
Annotate the opt-in native heap-gotter cdylib build knobs and helpers in setup.py: the NATIVE_HEAP_GOTTER_CRATE / BUILD_NATIVE_HEAP_GOTTER module globals and the build_heap_gotter / _clean_stale_heap_gotter methods (signatures + locals).
Match the linux wheel CI pattern used for _native: extract .debug sidecars with objcopy/strip at staging time so dogfood wheels ship a stripped libdd_heap_gotter.so, while CI debug-symbols.zip still collects the sidecar.
Switch the native heap gotter cdylib to mirror upstream libdd-profiling-heap-gotter-ffi (libdatadog@56dab857b), expose ddog_* / VoidResult symbols, stage liblibdd_profiling_heap_gotter_ffi artifacts, and add a fail-closed Python ctypes activator with smoke tests.
auditwheel iter_versions crashes on the opt-in heap-gotter cdylib ELF when DD_PROFILING_NATIVE_HEAP_BUILD=1, failing build-linux wheel jobs. Exclude the gotter artifact from repair, matching extract_debug_symbols ignores.
Rename to build(profiling) so changelog/no-changelog is allowed for this inert cdylib packaging change (no customer-facing behavior yet).
Required for feat PR changelog validation after removing no-changelog label.
Build-only native heap-gotter cdylib wiring has no customer-facing release note.
484088e to
a7e3bbb
Compare
Dependency direction analysis
|
…(PROF-15753) (#19079) ## Description Makes the heap-gotter cdylib from #19078 reachable: dd-trace-py can now *arm* native (C/C++) heap allocation profiling at profiler startup. All the heavy lifting of attaching uprobes, collecting, symbolizing, uploading is done by the OpenTelemetry eBPF profiler and DD FH profiler out of process. ### Changes * Activator > New `ddtrace.internal.datadog.profiling.heap_gotter`: a small `ctypes` wrapper over the cdylib's two-function C ABI (`install()`, `is_installed()`). The `CDLL` handle is held at module scope for the life of the process and never unloaded, because GOT patching cannot be undone. `install()` is idempotent and fork-safe: children inherit both the mapping and the patched GOT, so a post-fork re-install is a no-op. * Configuration > Adds `DD_PROFILING_NATIVE_HEAP_ENABLED` (boolean, default `false`) as a `native_heap` namespace on `ProfilingConfig`, registered in `supported-configurations.json` and `_supported_configurations.py`. It is a co-requirement, not a standalone switch: arming happens inside profiler startup, and the profiler only starts when `DD_PROFILING_ENABLED=true` (`ddtrace/bootstrap/preload.py` gates on `profiling_config.enabled`), so the native-heap flag alone does nothing. Availability is resolved lazily and only when the flag is on — the disabled path never even imports the activator, let alone `dlopen`s anything. If the flag is on but the cdylib cannot be loaded, the config is forced back off with a warning plus a telemetry error log rather than failing startup. When effectively on, `nativeheap` shows up in the `profiler_config` tag. * Profiler wiring > `_ProfilerInstance._start_service()` calls `heap_gotter.install()` when the feature is enabled, wrapped so that any failure is logged at debug level and swallowed — arming is best-effort and must never prevent the profiler from coming up. Also adds a narrow `mypy.ini` override for `ddtrace.internal.settings.profiling` (the untyped vendored `psutil` calls in the existing heap-sample-size derivation have no stubs in the lint env). ## Testing ### Unit * `tests/profiling/test_native_heap_gotter.py` * `tests/profiling/test_profiling_config.py` — default-off, enable-via-env, and `nativeheap` presence/absence in the `profiler_config` tag string; plus fail-closed assertions on the activator that hold on any platform. ### Staging testing ## Risks No risk for opted-out users. Low risk for opted-in, as there was quite a bit of AB-testing the feature. Co-authored-by: vlad.scherbich <vlad.scherbich@datadoghq.com>
Description
Adds a standalone Rust
cdylib(src/native_heap_gotter/) wrapping libdatadog's crates.io cratelibdd-profiling-heap-gotter1.0.0behind a stable, ddtrace-owned C ABI:ddtrace_heap_gotter_install()/_is_installed()(→bool, idempotent/fork-safe) and_test_hook_hits()(→u64,test-supportfeature only, never shipped). Owning the cdylib ([lib] name = "dd_heap_gotter") yields a cleanlibdd_heap_gotter.soand fixed, unmangled symbols for the futurectypesactivator.DD_PROFILING_NATIVE_HEAP_BUILD=1on Linux 64-bit.setup.pyrunscargo build --release, stageslibdd_heap_gotter<EXT_SUFFIX>.sounderddtrace/internal/datadog/profiling/, sets the soname (patchelf), and adds it topackage_dataonly when the flag is set. Off by default → mainline wheels unaffected.ddheap:allocandddheap:freeUSDTs in native heap gotter (PROF-15753) #19079 (gated byDD_PROFILING_NATIVE_HEAP_ENABLED).Testing
cargo build --release --manifest-path src/native_heap_gotter/Cargo.tomlresolves against crates.io and produceslibdd_heap_gotter.so.DD_PROFILING_NATIVE_HEAP_BUILD=1(Linux 64-bit) ships the staged.sowith the expected soname..so.