diff --git a/ddtrace/internal/datadog/profiling/stack_v2/CMakeLists.txt b/ddtrace/internal/datadog/profiling/stack_v2/CMakeLists.txt index 81dffab0281..6e8b7e205c7 100644 --- a/ddtrace/internal/datadog/profiling/stack_v2/CMakeLists.txt +++ b/ddtrace/internal/datadog/profiling/stack_v2/CMakeLists.txt @@ -41,11 +41,11 @@ endif() # Add echion set(ECHION_COMMIT - "6ebe7dddb604aa97e89f072c0fc65c9785e023a0" # https://github.com/P403n1x87/echion/commit/6ebe7dddb604aa97e89f072c0fc65c9785e023a0 + "07d6dd21b6885231a4529bf101556ba962385112" # https://github.com/taegyunkim/echion/commit/07d6dd21b6885231a4529bf101556ba962385112 CACHE STRING "Commit hash of echion to use") FetchContent_Declare( echion - GIT_REPOSITORY "https://github.com/P403n1x87/echion.git" + GIT_REPOSITORY "https://github.com/taegyunkim/echion.git" GIT_TAG ${ECHION_COMMIT}) FetchContent_GetProperties(echion) diff --git a/ddtrace/internal/datadog/profiling/stack_v2/src/stack_v2.cpp b/ddtrace/internal/datadog/profiling/stack_v2/src/stack_v2.cpp index 1a3886f02d6..27c9ef79c45 100644 --- a/ddtrace/internal/datadog/profiling/stack_v2/src/stack_v2.cpp +++ b/ddtrace/internal/datadog/profiling/stack_v2/src/stack_v2.cpp @@ -191,6 +191,26 @@ stack_v2_set_adaptive_sampling(PyObject* Py_UNUSED(self), PyObject* args) Py_RETURN_NONE; } +static PyObject* +stack_v2_set_vm_read_mode(PyObject* self, PyObject* args) +{ + (void)self; + int new_vm_read_mode; + if (!PyArg_ParseTuple(args, "i", &new_vm_read_mode)) { + return NULL; + } + + if (new_vm_read_mode < 0 || new_vm_read_mode > 2) { + new_vm_read_mode = 0; + } + + if (!_set_vm_read_mode(new_vm_read_mode)) { + Py_RETURN_FALSE; + } + + Py_RETURN_TRUE; +} + static PyMethodDef _stack_v2_methods[] = { { "start", reinterpret_cast(stack_v2_start), METH_VARARGS | METH_KEYWORDS, "Start the sampler" }, { "stop", stack_v2_stop, METH_VARARGS, "Stop the sampler" }, @@ -206,6 +226,7 @@ static PyMethodDef _stack_v2_methods[] = { { "init_asyncio", stack_v2_init_asyncio, METH_VARARGS, "Initialise asyncio tracking" }, { "link_tasks", stack_v2_link_tasks, METH_VARARGS, "Link two tasks" }, { "set_adaptive_sampling", stack_v2_set_adaptive_sampling, METH_VARARGS, "Set adaptive sampling" }, + { "set_vm_read_mode", stack_v2_set_vm_read_mode, METH_VARARGS, "Set the VM reading mode" }, { NULL, NULL, 0, NULL } }; diff --git a/ddtrace/settings/profiling.py b/ddtrace/settings/profiling.py index f73bd5e55b1..f270eb638c2 100644 --- a/ddtrace/settings/profiling.py +++ b/ddtrace/settings/profiling.py @@ -84,6 +84,33 @@ def _check_for_stack_v2_available(): return stack_v2_is_available +def _check_for_stack_v2_mode(config): + if not config.v2_enabled and not _check_for_stack_v2_available(): + return "disabled" + + mode = config._v2_mode + if mode not in ("writev", "process_vm_readv", "sigtrap"): + mode = "process_vm_readv" + + # If we're here, then stack v2 has been imported by _check_for_stack_v2_available, so this will probably succeed + try: + from ddtrace.internal.datadog.profiling import stack_v2 + except Exception: + return "disabled" + + if "process_vm_readv" == mode and stack_v2.set_vm_read_mode(1): + return "process_vm_readv" + elif "sigtrap" == mode and stack_v2.set_vm_read_mode(2): + return "sigtrap" + + # If we're here, then either the other modes were not specified, or they failed--try writev as a failover + if stack_v2.set_vm_read_mode(0): + return "writev" + + # Boohoo, we failed + return "disabled" + + def _is_libdd_required(config): # This function consolidates the logic for force-enabling the libdd uploader. Otherwise this will get enabled in # a bunch of separate places and it'll be tough to manage. @@ -341,6 +368,15 @@ class ProfilingConfigStack(DDConfig): # V2 can't be enabled if stack collection is disabled or if pre-requisites are not met v2_enabled = DDConfig.d(bool, lambda c: _check_for_stack_v2_available() and c._v2_enabled and c.enabled) + _v2_mode = DDConfig.v( + str, + "v2_mode", + default="process_vm_readv", + help_type="String", + help="The mode to use for the v2 stack profiler. Can be one of 'writev', 'process_vm_readv', or 'sigtrap'.", + ) + v2_mode = DDConfig.d(str, lambda c: _check_for_stack_v2_mode(c)) + v2_adaptive_sampling = DDConfig.v( bool, "v2.adaptive_sampling.enabled",