Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
23 changes: 3 additions & 20 deletions ddtrace/internal/settings/profiling.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,23 +253,11 @@ class ProfilingConfigStack(DDConfig):
enabled = DDConfig.v(
bool,
"enabled",
default=True,
help_type="Boolean",
help="Whether to enable the stack profiler",
)

_v2_enabled = DDConfig.v(
bool,
"v2_enabled",
# Not yet supported on 3.14
default=sys.version_info < (3, 14),
help_type="Boolean",
help="Whether to enable the v2 stack profiler. Also enables the libdatadog collector.",
help="Whether to enable the stack profiler",
)

# V2 can't be enabled if stack collection is disabled or if pre-requisites are not met
v2_enabled = DDConfig.d(bool, lambda c: c._v2_enabled and c.enabled)

v2_adaptive_sampling = DDConfig.v(
bool,
"v2.adaptive_sampling.enabled",
Expand Down Expand Up @@ -388,16 +376,14 @@ class ProfilingConfigPytorch(DDConfig):
# We also need to check if stack_v2 module is available, and turn if off
# if it s not.
stack_v2_failure_msg, stack_v2_is_available = _check_for_stack_v2_available()
if config.stack.v2_enabled and not stack_v2_is_available:
if config.stack.enabled and not stack_v2_is_available:
msg = stack_v2_failure_msg or "stack_v2 not available"
logger.warning("Failed to load stack_v2 module (%s), falling back to v1 stack sampler", msg)
telemetry_writer.add_log(
TELEMETRY_LOG_LEVEL.ERROR,
"Failed to load stack_v2 module (%s), disabling profiling" % msg,
)
config.stack.v2_enabled = False
config.stack.enabled = False
config.enabled = False

# Enrich tags with git metadata and DD_TAGS
config.tags = _enrich_tags(config.tags)
Expand All @@ -406,10 +392,7 @@ class ProfilingConfigPytorch(DDConfig):
def config_str(config):
configured_features = []
if config.stack.enabled:
if config.stack.v2_enabled:
configured_features.append("stack_v2")
else:
configured_features.append("stack")
configured_features.append("stack_v2")
if config.lock.enabled:
configured_features.append("lock")
if config.memory.enabled:
Expand Down
2 changes: 1 addition & 1 deletion ddtrace/profiling/_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def _(asyncio: ModuleType) -> None:
if THREAD_LINK is None:
THREAD_LINK = _threading._ThreadLink()

init_stack_v2: bool = config.stack.v2_enabled and stack_v2.is_available
init_stack_v2: bool = config.stack.enabled and stack_v2.is_available

@partial(wrap, sys.modules["asyncio.events"].BaseDefaultEventLoopPolicy.set_event_loop)
def _(f, args, kwargs):
Expand Down
2 changes: 1 addition & 1 deletion ddtrace/profiling/collector/_task.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ from .. import _threading
from ddtrace.internal.settings.profiling import config


if (is_stack_v2 := config.stack.v2_enabled):
if (is_stack_v2 := config.stack.enabled):

@when_imported("gevent")
def _(gevent):
Expand Down
2 changes: 1 addition & 1 deletion ddtrace/profiling/collector/stack.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ class StackCollector(collector.PeriodicCollector):
ignore_profiler: bool = config.ignore_profiler,
endpoint_collection_enabled: typing.Optional[bool] = None,
tracer: typing.Optional[Tracer] = None,
_stack_collector_v2_enabled: bool = config.stack.v2_enabled):
_stack_collector_v2_enabled: bool = config.stack.enabled):
super().__init__(interval= _default_min_interval_time())
if max_time_usage_pct <= 0 or max_time_usage_pct > 100:
raise ValueError("Max time usage percent must be greater than 0 and smaller or equal to 100")
Expand Down
2 changes: 1 addition & 1 deletion ddtrace/profiling/collector/threading.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def _set_patch_target(

# Also patch threading.Thread so echion can track thread lifetimes
def init_stack_v2() -> None:
if config.stack.v2_enabled and stack_v2.is_available:
if config.stack.enabled and stack_v2.is_available:
_thread_set_native_id = ddtrace_threading.Thread._set_native_id # type: ignore[attr-defined]
_thread_bootstrap_inner = ddtrace_threading.Thread._bootstrap_inner # type: ignore[attr-defined]

Expand Down
2 changes: 0 additions & 2 deletions ddtrace/profiling/profiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ def __init__(
api_key: Optional[str] = None,
_memory_collector_enabled: bool = profiling_config.memory.enabled,
_stack_collector_enabled: bool = profiling_config.stack.enabled,
_stack_v2_enabled: bool = profiling_config.stack.v2_enabled,
_lock_collector_enabled: bool = profiling_config.lock.enabled,
_pytorch_collector_enabled: bool = profiling_config.pytorch.enabled,
enable_code_provenance: bool = profiling_config.code_provenance,
Expand All @@ -140,7 +139,6 @@ def __init__(
self.api_key: Optional[str] = api_key if api_key is not None else config._dd_api_key
self._memory_collector_enabled: bool = _memory_collector_enabled
self._stack_collector_enabled: bool = _stack_collector_enabled
self._stack_v2_enabled: bool = _stack_v2_enabled
self._lock_collector_enabled: bool = _lock_collector_enabled
self._pytorch_collector_enabled: bool = _pytorch_collector_enabled
self.enable_code_provenance: bool = enable_code_provenance
Expand Down
7 changes: 0 additions & 7 deletions tests/profiling_v2/collector/test_stack_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ async def hello():
span_type = ext.SpanTypes.WEB

p = profiler.Profiler(tracer=tracer)
assert p._profiler._stack_v2_enabled
p.start()
with tracer.trace("test_asyncio", resource=resource, span_type=span_type) as span:
span_id = span.span_id
Expand Down Expand Up @@ -135,7 +134,6 @@ def test_asyncio_start_profiler_from_process_before_importing_asyncio():
assert stack_v2.is_available, stack_v2.failure_msg

p = profiler.Profiler()
assert p._profiler._stack_v2_enabled
p.start()

import asyncio
Expand Down Expand Up @@ -265,7 +263,6 @@ def test_asyncio_start_profiler_from_process_before_starting_loop():
assert stack_v2.is_available, stack_v2.failure_msg

p = profiler.Profiler()
assert p._profiler._stack_v2_enabled
p.start()

# Start an asyncio loop BEFORE importing profiler modules
Expand Down Expand Up @@ -396,7 +393,6 @@ def test_asyncio_start_profiler_from_process_after_creating_loop():
assert stack_v2.is_available, stack_v2.failure_msg

p = profiler.Profiler()
assert p._profiler._stack_v2_enabled
p.start()

async def my_function():
Expand Down Expand Up @@ -522,7 +518,6 @@ def test_asyncio_import_profiler_from_process_after_starting_loop():
assert stack_v2.is_available, stack_v2.failure_msg

p = profiler.Profiler()
assert p._profiler._stack_v2_enabled
p.start()

async def my_function():
Expand Down Expand Up @@ -659,7 +654,6 @@ async def background_task_func() -> None:
assert stack_v2.is_available, stack_v2.failure_msg

p = profiler.Profiler()
assert p._profiler._stack_v2_enabled
p.start()

# Run tasks that should be tracked
Expand Down Expand Up @@ -787,7 +781,6 @@ async def background_task_func() -> None:
assert stack_v2.is_available, stack_v2.failure_msg

p = profiler.Profiler()
assert p._profiler._stack_v2_enabled
p.start()

# Run tasks that should be tracked
Expand Down
1 change: 0 additions & 1 deletion tests/profiling_v2/simple_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,4 @@
object()

print(os.getpid())
print(bootstrap.profiler._profiler._stack_v2_enabled)
sys.exit(42)
3 changes: 1 addition & 2 deletions tests/profiling_v2/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ def test_call_script():
assert exitcode == 0, (stdout, stderr)
else:
assert exitcode == 42, (stdout, stderr)
hello, interval, pid, stack_v2 = list(s.strip() for s in stdout.decode().strip().split("\n"))
hello, interval, pid = list(s.strip() for s in stdout.decode().strip().split("\n"))
assert hello == "hello world", stdout.decode().strip()
assert float(interval) >= 0.01, stdout.decode().strip()
assert stack_v2 == str(True)


@pytest.mark.skipif(not os.getenv("DD_PROFILE_TEST_GEVENT", False), reason="Not testing gevent")
Expand Down
1 change: 0 additions & 1 deletion tests/telemetry/test_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,6 @@ def test_app_started_event_configuration_override(test_agent_session, run_python
{"name": "DD_PROFILING_PYTORCH_EVENTS_LIMIT", "origin": "default", "value": 1000000},
{"name": "DD_PROFILING_SAMPLE_POOL_CAPACITY", "origin": "default", "value": 4},
{"name": "DD_PROFILING_STACK_ENABLED", "origin": "env_var", "value": False},
{"name": "DD_PROFILING_STACK_V2_ENABLED", "origin": "default", "value": PYTHON_VERSION_INFO < (3, 14)},
{"name": "DD_PROFILING_TAGS", "origin": "default", "value": ""},
{"name": "DD_PROFILING_TIMELINE_ENABLED", "origin": "default", "value": True},
{"name": "DD_PROFILING_UPLOAD_INTERVAL", "origin": "env_var", "value": 10.0},
Expand Down
Loading