Skip to content

feat(profiling): stack v2 vm read mode #13262

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ddtrace/internal/datadog/profiling/stack_v2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
21 changes: 21 additions & 0 deletions ddtrace/internal/datadog/profiling/stack_v2/src/stack_v2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<PyCFunction>(stack_v2_start), METH_VARARGS | METH_KEYWORDS, "Start the sampler" },
{ "stop", stack_v2_stop, METH_VARARGS, "Stop the sampler" },
Expand All @@ -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 }
};

Expand Down
36 changes: 36 additions & 0 deletions ddtrace/settings/profiling.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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",
Expand Down
Loading