diff --git a/benchmarks/ddtrace_run/scenario.py b/benchmarks/ddtrace_run/scenario.py index 72173b4773f..7380027652d 100644 --- a/benchmarks/ddtrace_run/scenario.py +++ b/benchmarks/ddtrace_run/scenario.py @@ -22,7 +22,7 @@ def run(self): # initialize subprocess args subp_cmd = [] - code = "import ddtrace; ddtrace.patch_all()\n" + code = "import ddtrace; ddtrace._patch_all()\n" if self.ddtrace_run: subp_cmd = ["ddtrace-run"] code = "" diff --git a/ddtrace/__init__.py b/ddtrace/__init__.py index b555d1117ca..63ebbbe97ad 100644 --- a/ddtrace/__init__.py +++ b/ddtrace/__init__.py @@ -24,7 +24,7 @@ import ddtrace.internal.telemetry # noqa: E402 from ._monkey import patch # noqa: E402 -from ._monkey import patch_all # noqa: E402 +from ._monkey import _patch_all # noqa: E402 from .internal.compat import PYTHON_VERSION_INFO # noqa: E402 from .internal.utils.deprecations import DDTraceDeprecationWarning # noqa: E402 from ddtrace._trace.pin import Pin # noqa: E402 @@ -56,7 +56,7 @@ __all__ = [ "patch", - "patch_all", + "_patch_all", "Pin", "Span", "Tracer", diff --git a/ddtrace/_monkey.py b/ddtrace/_monkey.py index d2306ace9ce..46be3401e93 100644 --- a/ddtrace/_monkey.py +++ b/ddtrace/_monkey.py @@ -7,11 +7,13 @@ from ddtrace.appsec import load_common_appsec_modules from ddtrace.internal.telemetry.constants import TELEMETRY_NAMESPACE +from ddtrace.vendor.debtcollector import deprecate from .appsec._iast._utils import _is_iast_enabled from .internal import telemetry from .internal.logger import get_logger from .internal.utils import formats +from .internal.utils.deprecations import DDTraceDeprecationWarning from .settings import _config as config @@ -209,6 +211,16 @@ def on_import(hook): def patch_all(**patch_modules): + deprecate( + "patch_all is deprecated and will be removed in a future version of the tracer.", + message="""patch_all is deprecated in favor of ``import ddtrace.auto`` and ``DD_PATCH_MODULES`` + environment variable if needed.""", + category=DDTraceDeprecationWarning, + ) + _patch_all(**patch_modules) + + +def _patch_all(**patch_modules): # type: (bool) -> None """Enables ddtrace library instrumentation. @@ -219,7 +231,7 @@ def patch_all(**patch_modules): :param dict patch_modules: Override whether particular modules are patched or not. - >>> patch_all(redis=False, cassandra=False) + >>> _patch_all(redis=False, cassandra=False) """ modules = PATCH_MODULES.copy() diff --git a/ddtrace/bootstrap/preload.py b/ddtrace/bootstrap/preload.py index 0018162beaa..baf98eb5c69 100644 --- a/ddtrace/bootstrap/preload.py +++ b/ddtrace/bootstrap/preload.py @@ -104,7 +104,7 @@ def _(_): LLMObs.enable() if asbool(os.getenv("DD_TRACE_ENABLED", default=True)): - from ddtrace import patch_all + from ddtrace import _patch_all @register_post_preload def _(): @@ -114,7 +114,7 @@ def _(): modules_to_patch = os.getenv("DD_PATCH_MODULES") modules_to_str = parse_tags_str(modules_to_patch) modules_to_bool = {k: asbool(v) for k, v in modules_to_str.items()} - patch_all(**modules_to_bool) + _patch_all(**modules_to_bool) if config._trace_methods: _install_trace_methods(config._trace_methods) diff --git a/ddtrace/contrib/aws_lambda/__init__.py b/ddtrace/contrib/aws_lambda/__init__.py index f3d1c903374..b3e9612568c 100644 --- a/ddtrace/contrib/aws_lambda/__init__.py +++ b/ddtrace/contrib/aws_lambda/__init__.py @@ -14,7 +14,7 @@ ~~~~~~~~~~~~~~~~~~~~ This integration is configured automatically. The `datadog_lambda` package -calls ``patch_all`` when ``DD_TRACE_ENABLED`` is set to ``true``. +calls ``_patch_all`` when ``DD_TRACE_ENABLED`` is set to ``true``. It's not recommended to call ``patch`` for it manually. Since it would not do anything for other environments that do not meet the criteria above. diff --git a/ddtrace/contrib/httplib/__init__.py b/ddtrace/contrib/httplib/__init__.py index 948b885199a..0c5d5c092d5 100644 --- a/ddtrace/contrib/httplib/__init__.py +++ b/ddtrace/contrib/httplib/__init__.py @@ -8,15 +8,9 @@ The httplib integration is disabled by default. It can be enabled when using :ref:`ddtrace-run` or :ref:`import ddtrace.auto` -using the ``DD_TRACE_HTTPLIB_ENABLED`` environment variable:: +using the `DD_PATCH_MODULES` environment variable:: - DD_TRACE_HTTPLIB_ENABLED=true ddtrace-run .... - -The integration can also be enabled manually in code with -:func:`patch_all()`:: - - from ddtrace import patch_all - patch_all(httplib=True) + DD_PATCH_MODULES=httplib:true ddtrace-run .... Global Configuration diff --git a/ddtrace/contrib/internal/pytest/plugin.py b/ddtrace/contrib/internal/pytest/plugin.py index 52cf54a6f9c..ac773a2a086 100644 --- a/ddtrace/contrib/internal/pytest/plugin.py +++ b/ddtrace/contrib/internal/pytest/plugin.py @@ -175,4 +175,4 @@ def patch_all(request): import ddtrace if request.config.getoption("ddtrace-patch-all") or request.config.getini("ddtrace-patch-all"): - ddtrace.patch_all() + import ddtrace.auto # noqa: F401 diff --git a/ddtrace/contrib/kombu/__init__.py b/ddtrace/contrib/kombu/__init__.py index 1a010892a7b..1cd3dc92f6b 100644 --- a/ddtrace/contrib/kombu/__init__.py +++ b/ddtrace/contrib/kombu/__init__.py @@ -1,6 +1,7 @@ """Instrument kombu to report AMQP messaging. -``patch_all`` will not automatically patch your Kombu client to make it work, as this would conflict with the +ref:`import ddtrace.auto` and `ddtrace-run` will not automatically patch your Kombu client to +make it work, as this would conflict with the Celery integration. You must specifically request kombu be patched, as in the example below. Note: To permit distributed tracing for the kombu integration you must enable the tracer with priority @@ -8,14 +9,15 @@ https://ddtrace.readthedocs.io/en/stable/advanced_usage.html#priority-sampling Without enabling distributed tracing, spans within a trace generated by the kombu integration might be dropped -without the whole trace being dropped. +without the whole trace being dropped. Use either `DD_PATCH_MODULES=kombu:true` as an environment variable +or patch it manually with the following code: :: from ddtrace import patch from ddtrace.trace import Pin import kombu - # If not patched yet, you can patch kombu specifically + # Patch kombu patch(kombu=True) # This will report a span with the default settings diff --git a/ddtrace/contrib/sanic/__init__.py b/ddtrace/contrib/sanic/__init__.py index 96f47d156ac..a494eae7b58 100644 --- a/ddtrace/contrib/sanic/__init__.py +++ b/ddtrace/contrib/sanic/__init__.py @@ -8,8 +8,7 @@ Sanic tracing can also be enabled explicitly:: - from ddtrace import patch_all - patch_all(sanic=True) + import ddtrace.auto from sanic import Sanic from sanic.response import text diff --git a/ddtrace/contrib/snowflake/__init__.py b/ddtrace/contrib/snowflake/__init__.py index db137130214..cdd25744175 100644 --- a/ddtrace/contrib/snowflake/__init__.py +++ b/ddtrace/contrib/snowflake/__init__.py @@ -16,12 +16,6 @@ from ddtrace import patch patch(snowflake=True) -or use :func:`patch_all()` to manually enable the integration:: - - from ddtrace import patch_all - patch_all(snowflake=True) - - Global Configuration diff --git a/ddtrace/contrib/urllib3/__init__.py b/ddtrace/contrib/urllib3/__init__.py index 0f2ebf2b12f..3dc1ad80fb3 100644 --- a/ddtrace/contrib/urllib3/__init__.py +++ b/ddtrace/contrib/urllib3/__init__.py @@ -6,14 +6,12 @@ Enabling ~~~~~~~~ -The ``urllib3`` integration is not enabled by default. Use ``patch_all()`` -with the environment variable ``DD_TRACE_URLLIB3_ENABLED`` set, or call -:func:`patch()` with the ``urllib3`` argument set to ``True`` to manually -enable the integration, before importing and using ``urllib3``:: - - from ddtrace import patch - patch(urllib3=True) +The ``urllib3`` integration is not enabled by default. Use either ``ddtrace-run`` +or ``import ddtrace.auto`` with ``DD_PATCH_MODULES`` to enable it. +``DD_PATCH_MODULES=urllib3 ddtrace-run python app.py`` or +``DD_PATCH_MODULES=urllib3:true python app.py``:: + import ddtrace.auto # use urllib3 like usual diff --git a/docs/api.rst b/docs/api.rst index d4b4e80674a..cc8522778c0 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -9,8 +9,6 @@ Tracing .. automodule:: ddtrace.auto -.. autofunction:: ddtrace.patch_all - .. autofunction:: ddtrace.patch .. autoclass:: ddtrace.Tracer diff --git a/releasenotes/notes/deprecate_patch_all-244eddcfacb1da14.yaml b/releasenotes/notes/deprecate_patch_all-244eddcfacb1da14.yaml new file mode 100644 index 00000000000..de3518386cf --- /dev/null +++ b/releasenotes/notes/deprecate_patch_all-244eddcfacb1da14.yaml @@ -0,0 +1,4 @@ +--- +deprecations: + - | + tracer: ``patch_all`` is deprecated and will be removed in 3.0. As an alternative to ``patch_all``, you can use ``import ddtrace.auto`` along with ``DD_PATCH_MODULES`` if specific module patching is necessary. diff --git a/tests/appsec/iast/fixtures/entrypoint/views.py b/tests/appsec/iast/fixtures/entrypoint/views.py index 3359e5c0366..7c987ca1af3 100644 --- a/tests/appsec/iast/fixtures/entrypoint/views.py +++ b/tests/appsec/iast/fixtures/entrypoint/views.py @@ -22,9 +22,9 @@ def add_test(): def create_app_patch_all(): - from ddtrace import patch_all + from ddtrace import _patch_all - patch_all() + _patch_all() app = Flask(__name__) return app diff --git a/tests/commands/test_runner.py b/tests/commands/test_runner.py index b6ad3cbd755..237b37a39af 100644 --- a/tests/commands/test_runner.py +++ b/tests/commands/test_runner.py @@ -144,7 +144,7 @@ def test_dogstatsd_client_env_url_path(self): def test_patch_modules_from_env(self): """ - DD_PATCH_MODULES overrides the defaults for patch_all() + DD_PATCH_MODULES overrides the defaults for _patch_all() """ with self.override_env( env=dict( diff --git a/tests/contrib/algoliasearch/test.py b/tests/contrib/algoliasearch/test.py index 87f5f7b6910..4c8ff01587d 100644 --- a/tests/contrib/algoliasearch/test.py +++ b/tests/contrib/algoliasearch/test.py @@ -1,5 +1,5 @@ +from ddtrace import _patch_all from ddtrace import config -from ddtrace import patch_all from ddtrace.contrib.internal.algoliasearch.patch import algoliasearch_version from ddtrace.contrib.internal.algoliasearch.patch import patch from ddtrace.contrib.internal.algoliasearch.patch import unpatch @@ -156,7 +156,7 @@ def test_patch_unpatch(self): assert len(spans) == 1 def test_patch_all_auto_enable(self): - patch_all() + _patch_all() Pin.override(self.index, tracer=self.tracer) self.perform_search("test search") @@ -178,7 +178,7 @@ def test_user_specified_service_default(self): When a service name is specified by the user The algoliasearch integration shouldn't use it as the service name """ - patch_all() + _patch_all() Pin.override(self.index, tracer=self.tracer) self.perform_search("test search") spans = self.get_spans() @@ -194,7 +194,7 @@ def test_user_specified_service_v0(self): When a service name is specified by the user The algoliasearch integration shouldn't use it as the service name """ - patch_all() + _patch_all() Pin.override(self.index, tracer=self.tracer) self.perform_search("test search") spans = self.get_spans() @@ -210,7 +210,7 @@ def test_user_specified_service_v1(self): In the v1 service name schema, services default to $DD_SERVICE, so make sure that is used and not the v0 schema 'algoliasearch' """ - patch_all() + _patch_all() Pin.override(self.index, tracer=self.tracer) self.perform_search("test search") spans = self.get_spans() @@ -222,7 +222,7 @@ def test_user_specified_service_v1(self): @TracerTestCase.run_in_subprocess(env_overrides=dict(DD_TRACE_SPAN_ATTRIBUTE_SCHEMA="v0")) def test_span_name_v0_schema(self): - patch_all() + _patch_all() Pin.override(self.index, tracer=self.tracer) self.perform_search("test search") spans = self.get_spans() @@ -234,7 +234,7 @@ def test_span_name_v0_schema(self): @TracerTestCase.run_in_subprocess(env_overrides=dict(DD_TRACE_SPAN_ATTRIBUTE_SCHEMA="v1")) def test_span_name_v1_schema(self): - patch_all() + _patch_all() Pin.override(self.index, tracer=self.tracer) self.perform_search("test search") spans = self.get_spans() diff --git a/tests/contrib/django/test_django.py b/tests/contrib/django/test_django.py index 7b8a0e18ef7..53296f17a8b 100644 --- a/tests/contrib/django/test_django.py +++ b/tests/contrib/django/test_django.py @@ -2018,7 +2018,7 @@ def test_django_use_handler_resource_format_env(client, test_spans): "python", "-c", ( - "from ddtrace import config, patch_all; patch_all(); " + "from ddtrace import config, _patch_all; _patch_all(); " "import django; " "assert config.django.use_handler_resource_format; print('Test success')" ), @@ -2037,7 +2037,7 @@ def test_django_use_handler_with_url_name_resource_format_env(client, test_spans "python", "-c", ( - "from ddtrace import config, patch_all; patch_all(); " + "from ddtrace import config, _patch_all; _patch_all(); " "import django; " "assert config.django.use_handler_with_url_name_resource_format; print('Test success')" ), @@ -2117,7 +2117,7 @@ def test_django_use_legacy_resource_format_env(client, test_spans): "python", "-c", ( - "from ddtrace import config, patch_all; patch_all(); " + "from ddtrace import config, _patch_all; _patch_all(); " "import django; " "assert config.django.use_legacy_resource_format; print('Test success')" ), diff --git a/tests/contrib/psycopg/test_psycopg_snapshot.py b/tests/contrib/psycopg/test_psycopg_snapshot.py index c4f904bfaa4..e79bbaf0eda 100644 --- a/tests/contrib/psycopg/test_psycopg_snapshot.py +++ b/tests/contrib/psycopg/test_psycopg_snapshot.py @@ -72,7 +72,7 @@ def test_connect_traced_via_env(run_python_code_in_subprocess): import ddtrace from tests.contrib.config import POSTGRES_CONFIG -ddtrace.patch_all() +ddtrace._patch_all() conn = psycopg.connect(**POSTGRES_CONFIG) assert conn diff --git a/tests/contrib/psycopg2/test_psycopg.py b/tests/contrib/psycopg2/test_psycopg.py index 902d24d3c0e..e8b13ddd67d 100644 --- a/tests/contrib/psycopg2/test_psycopg.py +++ b/tests/contrib/psycopg2/test_psycopg.py @@ -247,9 +247,9 @@ def test_manual_wrap_extension_adapt(self): @skipIf(PSYCOPG2_VERSION < (2, 7), "quote_ident not available in psycopg2<2.7") def test_manual_wrap_extension_quote_ident(self): - from ddtrace import patch_all + from ddtrace import _patch_all - patch_all() + _patch_all() from psycopg2.extensions import quote_ident # NOTE: this will crash if it doesn't work. @@ -497,9 +497,9 @@ def test_postgres_dbm_propagation_comment(self): @skipIf(PSYCOPG2_VERSION < (2, 7), "quote_ident not available in psycopg2<2.7") def test_manual_wrap_extension_quote_ident_standalone(): - from ddtrace import patch_all + from ddtrace import _patch_all - patch_all() + _patch_all() from psycopg2.extensions import quote_ident # NOTE: this will crash if it doesn't work. diff --git a/tests/contrib/psycopg2/test_psycopg_snapshot.py b/tests/contrib/psycopg2/test_psycopg_snapshot.py index 6947faf15b8..e1b98c6d0d8 100644 --- a/tests/contrib/psycopg2/test_psycopg_snapshot.py +++ b/tests/contrib/psycopg2/test_psycopg_snapshot.py @@ -54,7 +54,7 @@ def test_connect_traced_via_env(run_python_code_in_subprocess): import ddtrace from tests.contrib.config import POSTGRES_CONFIG -ddtrace.patch_all() +ddtrace._patch_all() conn = psycopg2.connect(**POSTGRES_CONFIG) assert conn diff --git a/tests/contrib/starlette/test_starlette.py b/tests/contrib/starlette/test_starlette.py index f290ade8ea7..d8f39499564 100644 --- a/tests/contrib/starlette/test_starlette.py +++ b/tests/contrib/starlette/test_starlette.py @@ -497,7 +497,7 @@ def test_incorrect_patching(run_python_code_in_subprocess): from starlette.testclient import TestClient import sqlalchemy -from ddtrace import patch_all +from ddtrace import _patch_all from tests.contrib.starlette.app import get_app @@ -505,9 +505,9 @@ def test_incorrect_patching(run_python_code_in_subprocess): engine = sqlalchemy.create_engine("sqlite:///test.db") app = get_app(engine) -# Calling patch_all late +# Calling _patch_all late # DEV: The test client uses `requests` so we want to ignore them for this scenario -patch_all(requests=False, http=False) +_patch_all(requests=False, http=False) with TestClient(app) as test_client: r = test_client.get("/200") diff --git a/tests/tracer/test_monkey.py b/tests/tracer/test_monkey.py index 9b6f1ee86a6..bbd826f43b4 100644 --- a/tests/tracer/test_monkey.py +++ b/tests/tracer/test_monkey.py @@ -17,12 +17,12 @@ class TestPatching(SubprocessTestCase): @run_in_subprocess(env_overrides=dict()) def test_patch_all_env_override_sqlite_none(self): # Make sure sqlite is enabled by default. - _monkey.patch_all() + _monkey._patch_all() assert "sqlite3" in _monkey._PATCHED_MODULES @run_in_subprocess(env_overrides=dict(DD_TRACE_SQLITE3_ENABLED="false")) def test_patch_all_env_override_sqlite_disabled(self): - _monkey.patch_all() + _monkey._patch_all() assert "sqlite3" not in _monkey._PATCHED_MODULES @run_in_subprocess(env_overrides=dict(DD_TRACE_SQLITE3_ENABLED="false")) @@ -46,12 +46,12 @@ def test_patch_raise_exception_manual_patch(self): @run_in_subprocess(env_overrides=dict()) def test_patch_all_env_override_httplib_none(self): # Make sure httplib is disabled by default. - _monkey.patch_all() + _monkey._patch_all() assert "httplib" not in _monkey._PATCHED_MODULES @run_in_subprocess(env_overrides=dict(DD_TRACE_HTTPLIB_ENABLED="true")) def test_patch_all_env_override_httplib_enabled(self): - _monkey.patch_all() + _monkey._patch_all() assert "httplib" in _monkey._PATCHED_MODULES @run_in_subprocess()