Skip to content

Commit a5bf963

Browse files
authored
chore(integrations): internalize get_version, patch, and unpatch for all integrations [3.0] (#11916)
Requires: [chore: avoids using deprecated modules in tests and log injection [3.0 prep]](#11835). Follow up to: #11918 This change internalizes the following functions: - `ddtrace.contrib.<integration_name>.patch()` - `ddtrace.contrib.<integration_name>.unpatch()` - `ddtrace.contrib.<integration_name>.get_version()` This change also internalizes all integrations that only expose `patch()`, `unpatch()`, and `get_version()` functions. ## Checklist - [x] PR author has checked that all the criteria below are met - The PR description includes an overview of the change - The PR description articulates the motivation for the change - The change includes tests OR the PR description describes a testing strategy - The PR description notes risks associated with the change, if any - Newly-added code is easy to change - The change follows the [library release note guidelines](https://ddtrace.readthedocs.io/en/stable/releasenotes.html) - The change includes or references documentation updates if necessary - Backport labels are set (if [applicable](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)) ## Reviewer Checklist - [x] Reviewer has checked that all the criteria below are met - Title is accurate - All changes are related to the pull request's stated goal - Avoids breaking [API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces) changes - Testing strategy adequately addresses listed risks - Newly-added code is easy to change - Release note makes sense to a user of the library - If necessary, author has acknowledged and discussed the performance implications of this PR as reported in the benchmarks PR comment - Backport labels are set in a manner that is consistent with the [release branch maintenance policy](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)
1 parent a1b7b9d commit a5bf963

File tree

171 files changed

+1538
-1521
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

171 files changed

+1538
-1521
lines changed

ddtrace/_monkey.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,13 @@ def _on_import_factory(module, prefix="ddtrace.contrib", raise_errors=True, patc
176176

177177
def on_import(hook):
178178
# Import and patch module
179-
path = "%s.%s" % (prefix, module)
180179
try:
181-
imported_module = importlib.import_module(path)
180+
try:
181+
imported_module = importlib.import_module("%s.internal.%s.patch" % (prefix, module))
182+
except ImportError:
183+
# Some integrations do not have an internal patch module, so we use the public one
184+
# FIXME: This is a temporary solution until we refactor the patching logic.
185+
imported_module = importlib.import_module("%s.%s" % (prefix, module))
182186
imported_module.patch()
183187
if hasattr(imported_module, "patch_submodules"):
184188
imported_module.patch_submodules(patch_indicator)
@@ -204,7 +208,8 @@ def on_import(hook):
204208
telemetry.telemetry_writer.add_integration(
205209
name, True, PATCH_MODULES.get(module) is True, "", version=v
206210
)
207-
else:
211+
elif hasattr(imported_module, "get_version"):
212+
# TODO: Ensure every integration defines either get_version or get_versions in their patch.py module
208213
version = imported_module.get_version()
209214
telemetry.telemetry_writer.add_integration(
210215
module, True, PATCH_MODULES.get(module) is True, "", version=version

ddtrace/_trace/trace_handlers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from ddtrace.constants import SPAN_MEASURED_KEY
2323
from ddtrace.contrib import trace_utils
2424
from ddtrace.contrib.internal.botocore.constants import BOTOCORE_STEPFUNCTIONS_INPUT_KEY
25-
from ddtrace.contrib.trace_utils import _set_url_tag
25+
from ddtrace.contrib.internal.trace_utils import _set_url_tag
2626
from ddtrace.ext import SpanKind
2727
from ddtrace.ext import db
2828
from ddtrace.ext import http

ddtrace/_trace/utils_redis.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from ddtrace.constants import SPAN_KIND
1111
from ddtrace.constants import SPAN_MEASURED_KEY
1212
from ddtrace.contrib import trace_utils
13-
from ddtrace.contrib.redis_utils import _extract_conn_tags
13+
from ddtrace.contrib.internal.redis_utils import _extract_conn_tags
1414
from ddtrace.ext import SpanKind
1515
from ddtrace.ext import SpanTypes
1616
from ddtrace.ext import db

ddtrace/appsec/_handlers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
from ddtrace.appsec._asm_request_context import get_blocked
77
from ddtrace.appsec._constants import SPAN_DATA_NAMES
88
from ddtrace.contrib import trace_utils
9-
from ddtrace.contrib.trace_utils import _get_request_header_user_agent
10-
from ddtrace.contrib.trace_utils import _set_url_tag
9+
from ddtrace.contrib.internal.trace_utils import _get_request_header_user_agent
10+
from ddtrace.contrib.internal.trace_utils import _set_url_tag
1111
from ddtrace.ext import SpanTypes
1212
from ddtrace.ext import http
1313
from ddtrace.internal import core

ddtrace/appsec/_processor.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def get_rules() -> str:
101101

102102

103103
def _set_headers(span: Span, headers: Any, kind: str, only_asm_enabled: bool = False) -> None:
104-
from ddtrace.contrib.trace_utils import _normalize_tag_name
104+
from ddtrace.contrib.internal.trace_utils import _normalize_tag_name
105105

106106
for k in headers:
107107
if isinstance(k, tuple):
@@ -218,7 +218,7 @@ def rasp_sqli_enabled(self) -> bool:
218218
return WAF_DATA_NAMES.SQLI_ADDRESS in self._addresses_to_keep
219219

220220
def on_span_start(self, span: Span) -> None:
221-
from ddtrace.contrib import trace_utils
221+
from ddtrace.contrib.internal import trace_utils
222222

223223
if not hasattr(self, "_ddwaf"):
224224
self.delayed_init()

ddtrace/appsec/_trace_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from ddtrace.appsec._constants import LOGIN_EVENTS_MODE
1212
from ddtrace.appsec._constants import WAF_ACTIONS
1313
from ddtrace.appsec._utils import _hash_user_id
14-
from ddtrace.contrib.trace_utils import set_user
14+
from ddtrace.contrib.internal.trace_utils import set_user
1515
from ddtrace.ext import SpanTypes
1616
from ddtrace.ext import user
1717
from ddtrace.internal import core

ddtrace/appsec/_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def parse_response_body(raw_body):
2222

2323
from ddtrace.appsec import _asm_request_context
2424
from ddtrace.appsec._constants import SPAN_DATA_NAMES
25-
from ddtrace.contrib.trace_utils import _get_header_value_case_insensitive
25+
from ddtrace.contrib.internal.trace_utils import _get_header_value_case_insensitive
2626

2727
if not raw_body:
2828
return

ddtrace/contrib/__init__.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,73 @@
11
from ddtrace._trace import trace_handlers # noqa:F401
2+
from ddtrace.internal.utils.deprecations import DDTraceDeprecationWarning
23
from ddtrace.internal.utils.importlib import func_name # noqa:F401
34
from ddtrace.internal.utils.importlib import module_name # noqa:F401
45
from ddtrace.internal.utils.importlib import require_modules # noqa:F401
6+
from ddtrace.vendor.debtcollector import deprecate
7+
8+
9+
def __getattr__(name):
10+
if name in (
11+
"aiohttp",
12+
"asgi",
13+
"bottle",
14+
"celery",
15+
"cherrypy",
16+
"falcon",
17+
"flask_cache",
18+
"pylibmc",
19+
"pyramid",
20+
"requests",
21+
"sqlalchemy",
22+
"wsgi",
23+
"trace_utils",
24+
"internal",
25+
):
26+
# following packages/modules are not deprecated and will not be removed in 3.0
27+
pass
28+
elif name in ("trace_handlers", "func_name", "module_name", "require_modules"):
29+
# the following attributes are exposed in ddtrace.contrib.__init__ and should be
30+
# removed in v3.0
31+
deprecate(
32+
("ddtrace.contrib.%s is deprecated" % name),
33+
category=DDTraceDeprecationWarning,
34+
removal_version="3.0.0",
35+
)
36+
elif name in ("aiobotocore", "httplib", "kombu", "snowflake", "sqlalchemy", "tornado", "urllib3"):
37+
# following integrations are not enabled by default and require a unique deprecation message
38+
deprecate(
39+
f"ddtrace.contrib.{name} is deprecated",
40+
message="Avoid using this package directly. "
41+
f"Set DD_TRACE_{name.upper()}_ENABLED=true and use ``ddtrace.auto`` or the "
42+
"``ddtrace-run`` command to enable and configure this integration.",
43+
category=DDTraceDeprecationWarning,
44+
removal_version="3.0.0",
45+
)
46+
elif name in ("redis_utils", "trace_utils_redis", "trace_utils_async"):
47+
deprecate(
48+
f"The ddtrace.contrib.{name} module is deprecated",
49+
message="Import from ``ddtrace.contrib.trace_utils`` instead.",
50+
category=DDTraceDeprecationWarning,
51+
removal_version="3.0.0",
52+
)
53+
elif name == "flask_login":
54+
deprecate(
55+
"""The flask_login integration is deprecated and will be deleted.
56+
We recommend customers to switch to manual instrumentation.
57+
https://docs.datadoghq.com/security/application_security/threats/add-user-info/?tab=loginsuccess&code-lang=python#adding-business-logic-information-login-success-login-failure-any-business-logic-to-traces
58+
""",
59+
message="",
60+
category=DDTraceDeprecationWarning,
61+
)
62+
else:
63+
deprecate(
64+
f"ddtrace.contrib.{name} is deprecated",
65+
message="Avoid using this package directly. "
66+
f"Use ``import ddtrace.auto`` or the ``ddtrace-run`` command to enable and configure {name}.",
67+
category=DDTraceDeprecationWarning,
68+
removal_version="3.0.0",
69+
)
70+
71+
if name in globals():
72+
return globals()[name]
73+
raise AttributeError("%s has no attribute %s", __name__, name)

ddtrace/contrib/aiobotocore/__init__.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@
3535
_w.simplefilter("ignore", DeprecationWarning)
3636
from . import patch as _ # noqa: F401, I001
3737

38-
# Expose public methods
39-
from ddtrace.contrib.internal.aiobotocore.patch import get_version
40-
from ddtrace.contrib.internal.aiobotocore.patch import patch
4138

42-
43-
__all__ = ["patch", "get_version"]
39+
from ddtrace.contrib.internal.aiobotocore.patch import get_version # noqa: F401
40+
from ddtrace.contrib.internal.aiobotocore.patch import patch # noqa: F401

ddtrace/contrib/aiohttp/__init__.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,25 @@ async def home_handler(request):
9494
_w.simplefilter("ignore", DeprecationWarning)
9595
from . import patch as _ # noqa: F401, I001
9696
from ddtrace.contrib.internal.aiohttp.middlewares import trace_app
97-
from ddtrace.contrib.internal.aiohttp.patch import get_version
97+
from ddtrace.contrib.internal.aiohttp.patch import get_version # noqa: F401
98+
from ddtrace.contrib.internal.aiohttp.patch import patch # noqa: F401
99+
from ddtrace.contrib.internal.aiohttp.patch import unpatch # noqa: F401
100+
from ddtrace.internal.utils.deprecations import DDTraceDeprecationWarning
101+
from ddtrace.vendor.debtcollector import deprecate
98102

99-
# Expose public methods
100-
from ddtrace.contrib.internal.aiohttp.patch import patch
101-
from ddtrace.contrib.internal.aiohttp.patch import unpatch
102103

104+
def __getattr__(name):
105+
if name in ("patch", "get_version", "unpatch"):
106+
deprecate(
107+
("%s.%s is deprecated" % (__name__, name)),
108+
message="Use ``import ddtrace.auto`` or the ``ddtrace-run`` command to configure this integration.",
109+
category=DDTraceDeprecationWarning,
110+
removal_version="3.0.0",
111+
)
103112

104-
__all__ = ["patch", "unpatch", "trace_app", "get_version"]
113+
if name in globals():
114+
return globals()[name]
115+
raise AttributeError("%s has no attribute %s", __name__, name)
116+
117+
118+
__all__ = ["trace_app"]

0 commit comments

Comments
 (0)