|
4 | 4 | libdatadog's ``libdd-profiling-heap-gotter-ffi``; see ``src/native_heap_gotter``) |
5 | 5 | and drives it through a tiny, stable C ABI: |
6 | 6 |
|
7 | | - bool ddtrace_heap_gotter_install(void); # install + report success |
8 | | - bool ddtrace_heap_gotter_is_installed(void); # current install state |
| 7 | + bool ddtrace_heap_gotter_install(void); # install + report success |
| 8 | + bool ddtrace_heap_gotter_is_installed(void); # current install state |
| 9 | + bool ddtrace_heap_gotter_live_heap_enabled(void); # built with ddheap:free? |
9 | 10 |
|
10 | 11 | Calling ``install()`` patches the process's GOT entries for heap allocation |
11 | | -symbols so that Datadog's ``ddheap:alloc`` (Phase 1: allocation-only) USDT probe |
12 | | -sites fire on sampled allocations. The Full Host eBPF profiler then attaches |
13 | | -uprobes to those sites to collect native allocation flamegraphs. There is |
14 | | -nothing to collect or upload from the Python side — this only *arms* the probes. |
| 12 | +symbols so that Datadog's ``ddheap:alloc`` USDT probe sites fire on sampled |
| 13 | +allocations. The Full Host eBPF profiler then attaches uprobes to those sites to |
| 14 | +collect native allocation flamegraphs. There is nothing to collect or upload |
| 15 | +from the Python side — this only *arms* the probes. |
| 16 | +
|
| 17 | +``live_heap_enabled()`` reports whether the loaded cdylib was *built* with |
| 18 | +live-heap tracking, in which case it also emits the ``ddheap:free`` USDT and |
| 19 | +stamps a per-allocation retain flag so the FH profiler can reconcile frees |
| 20 | +against allocations for a live/retained-heap view. Live-heap is a default of the |
| 21 | +gotter build, so any current cdylib reports ``True``; the query stays as a |
| 22 | +defensive check that reflects the *actual* loaded artifact — an older alloc-only |
| 23 | +cdylib (or a cdylib built before this symbol existed) reports ``False`` (the |
| 24 | +symbol is bound defensively). This is a compile-time property, not a runtime |
| 25 | +toggle. |
15 | 26 |
|
16 | 27 | Fail-closed by design: if the cdylib is missing (the default, since it only |
17 | 28 | ships when built with ``DD_PROFILING_NATIVE_HEAP_BUILD=1``) or anything goes |
|
37 | 48 | is_available: bool = False |
38 | 49 | failure_msg: str = "" |
39 | 50 |
|
| 51 | +# Whether the loaded cdylib was built with live-heap tracking (ddheap:free + |
| 52 | +# retain flagging). Compile-time property of the artifact; see module docstring. |
| 53 | +# Stays False when the cdylib is absent or was built allocation-only. |
| 54 | +_live_heap_available: bool = False |
| 55 | + |
40 | 56 | _lib: ctypes.CDLL | None = None # kept alive for process lifetime; never dlclose'd |
41 | 57 |
|
42 | 58 |
|
@@ -69,6 +85,16 @@ def _library_path() -> str: |
69 | 85 |
|
70 | 86 | is_available = True |
71 | 87 |
|
| 88 | + # Bind the live-heap capability query defensively: it only exists on cdylibs |
| 89 | + # built at/after Phase 2. A missing symbol (older alloc-only build) simply |
| 90 | + # leaves live-heap reported as unavailable rather than failing the load. |
| 91 | + try: |
| 92 | + _lib.ddtrace_heap_gotter_live_heap_enabled.argtypes = [] |
| 93 | + _lib.ddtrace_heap_gotter_live_heap_enabled.restype = ctypes.c_bool |
| 94 | + _live_heap_available = bool(_lib.ddtrace_heap_gotter_live_heap_enabled()) |
| 95 | + except AttributeError: |
| 96 | + _live_heap_available = False |
| 97 | + |
72 | 98 | except Exception as e: |
73 | 99 | failure_msg = str(e) |
74 | 100 | _lib = None |
@@ -96,3 +122,15 @@ def is_installed() -> bool: |
96 | 122 | return bool(_lib.ddtrace_heap_gotter_is_installed()) |
97 | 123 | except Exception: |
98 | 124 | return False |
| 125 | + |
| 126 | + |
| 127 | +def live_heap_enabled() -> bool: |
| 128 | + """Return whether the loaded cdylib was built with live-heap tracking. |
| 129 | +
|
| 130 | + Live-heap is a default of the gotter build, so any current cdylib returns |
| 131 | + True: it emits the ``ddheap:free`` USDT and stamps a per-allocation retain |
| 132 | + flag so the FH profiler can reconcile frees against allocations. A missing |
| 133 | + cdylib, or an older alloc-only one, returns False. Compile-time property; it |
| 134 | + does not change over the process lifetime. |
| 135 | + """ |
| 136 | + return _live_heap_available |
0 commit comments