Skip to content
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

chore(core): disable crashtracking by default #10912

Draft
wants to merge 1 commit 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
37 changes: 24 additions & 13 deletions ddtrace/internal/core/crashtracking.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,49 @@
from typing import Callable

from ddtrace import config
from ddtrace import version
from ddtrace.internal import agent
from ddtrace.internal.datadog.profiling import crashtracker
from ddtrace.internal.runtime import get_runtime_id
from ddtrace.internal.runtime import on_runtime_id_change
from ddtrace.settings.crashtracker import config as crashtracker_config


is_available: bool = crashtracker.is_available
failure_msg: str = crashtracker.failure_msg
is_started: Callable[[], bool] = crashtracker.is_started
is_enabled_and_available = False
if crashtracker_config.enabled:
try:
from ddtrace.internal.datadog.profiling import crashtracker

is_enabled_and_available = crashtracker.is_available
except ImportError:
is_enabled_and_available = False


# DEV crashtracker was once loaded and enabled by default everywhere, but due to consequences of running long-running
# child processes, it has been disabled by default. Hoping to reenable it soon. Pushing the module imports down
# into individual functions is not a design requirement, but rather a way to avoid loading the module until needed.


@on_runtime_id_change
def _update_runtime_id(runtime_id: str) -> None:
crashtracker.set_runtime_id(runtime_id)
if is_enabled_and_available:
from ddtrace.internal.datadog.profiling import crashtracker

crashtracker.set_runtime_id(runtime_id)


def add_tag(key: str, value: str) -> None:
if is_available:
if is_enabled_and_available:
from ddtrace.internal.datadog.profiling import crashtracker

crashtracker.set_tag(key, value)


def start() -> bool:
if not is_available:
if not is_enabled_and_available:
return False

import platform

from ddtrace.internal.datadog.profiling import crashtracker

crashtracker.set_url(crashtracker_config.debug_url or agent.get_trace_url())
crashtracker.set_service(config.service)
crashtracker.set_version(config.version)
Expand Down Expand Up @@ -57,7 +71,4 @@ def start() -> bool:
for key, value in crashtracker_config.tags.items():
add_tag(key, value)

# Only start if it is enabled
if crashtracker_config.enabled:
return crashtracker.start()
return False
return crashtracker.start()
32 changes: 18 additions & 14 deletions tests/internal/crashtracker/test_crashtracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@


@pytest.mark.skipif(not sys.platform.startswith("linux"), reason="Linux only")
@pytest.mark.subprocess()
@pytest.mark.subprocess(env={"DD_CRASHTRACKING_ENABLED": "true"})
def test_crashtracker_available():
import ddtrace.internal.datadog.profiling.crashtracker as crashtracker

assert crashtracker.is_available


@pytest.mark.skipif(not sys.platform.startswith("linux"), reason="Linux only")
@pytest.mark.subprocess()
@pytest.mark.subprocess(env={"DD_CRASHTRACKING_ENABLED": "true"})
def test_crashtracker_config():
import pytest

Expand All @@ -29,7 +29,7 @@ def test_crashtracker_config():


@pytest.mark.skipif(not sys.platform.startswith("linux"), reason="Linux only")
@pytest.mark.subprocess()
@pytest.mark.subprocess(env={"DD_CRASHTRACKING_ENABLED": "true"})
def test_crashtracker_config_bytes():
import pytest

Expand Down Expand Up @@ -58,7 +58,7 @@ def test_crashtracker_config_bytes():


@pytest.mark.skipif(not sys.platform.startswith("linux"), reason="Linux only")
@pytest.mark.subprocess()
@pytest.mark.subprocess(env={"DD_CRASHTRACKING_ENABLED": "true"})
def test_crashtracker_started():
import pytest

Expand All @@ -79,7 +79,7 @@ def test_crashtracker_started():


@pytest.mark.skipif(not sys.platform.startswith("linux"), reason="Linux only")
@pytest.mark.subprocess()
@pytest.mark.subprocess(env={"DD_CRASHTRACKING_ENABLED": "true"})
def test_crashtracker_simple():
# This test does the following
# 1. Finds a random port in the range 10000-20000 it can bind to (5 retries)
Expand Down Expand Up @@ -122,7 +122,7 @@ def test_crashtracker_simple():


@pytest.mark.skipif(not sys.platform.startswith("linux"), reason="Linux only")
@pytest.mark.subprocess()
@pytest.mark.subprocess(env={"DD_CRASHTRACKING_ENABLED": "true"})
def test_crashtracker_simple_fork():
# This is similar to the simple test, except crashtracker initialization is done
# in the parent
Expand Down Expand Up @@ -158,7 +158,7 @@ def test_crashtracker_simple_fork():


@pytest.mark.skipif(not sys.platform.startswith("linux"), reason="Linux only")
@pytest.mark.subprocess()
@pytest.mark.subprocess(env={"DD_CRASHTRACKING_ENABLED": "true"})
def test_crashtracker_simple_sigbus():
# This is similar to the simple fork test, except instead of raising a SIGSEGV,
# it organically raises a real SIGBUS.
Expand Down Expand Up @@ -214,7 +214,7 @@ def test_crashtracker_simple_sigbus():


@pytest.mark.skipif(not sys.platform.startswith("linux"), reason="Linux only")
@pytest.mark.subprocess()
@pytest.mark.subprocess(env={"DD_CRASHTRACKING_ENABLED": "true"})
def test_crashtracker_raise_sigsegv():
import os
import signal
Expand Down Expand Up @@ -247,7 +247,7 @@ def test_crashtracker_raise_sigsegv():


@pytest.mark.skipif(not sys.platform.startswith("linux"), reason="Linux only")
@pytest.mark.subprocess()
@pytest.mark.subprocess(env={"DD_CRASHTRACKING_ENABLED": "true"})
def test_crashtracker_raise_sigbus():
import os
import signal
Expand Down Expand Up @@ -295,6 +295,7 @@ def test_crashtracker_preload_default(ddtrace_run_python_code_in_subprocess):
# Call the program
env = os.environ.copy()
env["DD_TRACE_AGENT_URL"] = "http://localhost:%d" % port
env["DD_CRASHTRACKING_ENABLED"] = "true"
stdout, stderr, exitcode, _ = ddtrace_run_python_code_in_subprocess(preload_code, env=env)

# Check for expected exit condition
Expand All @@ -320,7 +321,7 @@ def test_crashtracker_preload_disabled(ddtrace_run_python_code_in_subprocess):
# Call the program
env = os.environ.copy()
env["DD_TRACE_AGENT_URL"] = "http://localhost:%d" % port
env["DD_CRASHTRACKING_ENABLED"] = "false"
env["DD_CRASHTRACKING_ENABLED"] = "true"
stdout, stderr, exitcode, _ = ddtrace_run_python_code_in_subprocess(preload_code, env=env)

# Check for expected exit condition
Expand All @@ -342,14 +343,15 @@ def test_crashtracker_preload_disabled(ddtrace_run_python_code_in_subprocess):


@pytest.mark.skipif(not sys.platform.startswith("linux"), reason="Linux only")
def test_crashtracker_auto_default(run_python_code_in_subprocess):
def test_crashtracker_auto_enabled(run_python_code_in_subprocess):
# Setup the listening socket before we open ddtrace
port, sock = utils.crashtracker_receiver_bind()
assert sock

# Call the program
env = os.environ.copy()
env["DD_TRACE_AGENT_URL"] = "http://localhost:%d" % port
env["DD_CRASHTRACKING_ENABLED"] = "true"
stdout, stderr, exitcode, _ = run_python_code_in_subprocess(auto_code, env=env)

# Check for expected exit condition
Expand All @@ -376,6 +378,7 @@ def test_crashtracker_auto_nostack(run_python_code_in_subprocess):
env = os.environ.copy()
env["DD_TRACE_AGENT_URL"] = "http://localhost:%d" % port
env["DD_CRASHTRACKING_STACKTRACE_RESOLVER"] = "none"
env["DD_CRASHTRACKING_ENABLED"] = "true"
stdout, stderr, exitcode, _ = run_python_code_in_subprocess(auto_code, env=env)

# Check for expected exit condition
Expand Down Expand Up @@ -415,7 +418,7 @@ def test_crashtracker_auto_disabled(run_python_code_in_subprocess):


@pytest.mark.skipif(not sys.platform.startswith("linux"), reason="Linux only")
@pytest.mark.subprocess()
@pytest.mark.subprocess(env={"DD_CRASHTRACKING_ENABLED": "true"})
def test_crashtracker_tags_required():
# Tests tag ingestion in the core API
import ctypes
Expand Down Expand Up @@ -462,6 +465,7 @@ def test_crashtracker_user_tags_envvar(run_python_code_in_subprocess):
# Call the program
env = os.environ.copy()
env["DD_TRACE_AGENT_URL"] = "http://localhost:%d" % port
env["DD_CRASHTRACKING_ENABLED"] = "true"

# Injecting tags, but since the way we validate them is with a raw-data string search, we make things unique
tag_prefix = "cryptocrystalline"
Expand Down Expand Up @@ -490,7 +494,7 @@ def test_crashtracker_user_tags_envvar(run_python_code_in_subprocess):


@pytest.mark.skipif(not sys.platform.startswith("linux"), reason="Linux only")
@pytest.mark.subprocess()
@pytest.mark.subprocess(env={"DD_CRASHTRACKING_ENABLED": "true"})
def test_crashtracker_user_tags_profiling():
# Tests tag ingestion in the backend API (which is currently out of profiling)
import ctypes
Expand Down Expand Up @@ -536,7 +540,7 @@ def test_crashtracker_user_tags_profiling():


@pytest.mark.skipif(not sys.platform.startswith("linux"), reason="Linux only")
@pytest.mark.subprocess()
@pytest.mark.subprocess(env={"DD_CRASHTRACKING_ENABLED": "true"})
def test_crashtracker_user_tags_core():
# Tests tag ingestion in the core API
import ctypes
Expand Down
Loading