Skip to content

Commit 06b2266

Browse files
authored
Merge branch '4.0-breaking-changes' into taegyunkim/remove-stack-v1
2 parents c412a40 + 1c95d17 commit 06b2266

File tree

17 files changed

+261
-115
lines changed

17 files changed

+261
-115
lines changed

ddtrace/_trace/span.py

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -269,19 +269,6 @@ def start(self, value: Union[int, float]) -> None:
269269
def finished(self) -> bool:
270270
return self.duration_ns is not None
271271

272-
@finished.setter
273-
def finished(self, value: bool) -> None:
274-
"""Finishes the span if set to a truthy value.
275-
276-
If the span is already finished and a truthy value is provided
277-
no action will occur.
278-
"""
279-
if value:
280-
if not self.finished:
281-
self.duration_ns = Time.time_ns() - self.start_ns
282-
else:
283-
self.duration_ns = None
284-
285272
@property
286273
def duration(self) -> Optional[float]:
287274
"""The span duration in seconds."""
@@ -604,8 +591,6 @@ def record_exception(
604591
:param attributes: Optional dictionary of additional attributes to add to the exception event.
605592
These attributes will override the default exception attributes if they contain the same keys.
606593
Valid attribute values include (homogeneous array of) strings, booleans, integers, floats.
607-
:param timestamp: Deprecated.
608-
:param escaped: Deprecated.
609594
"""
610595
tb = self._get_traceback(type(exception), exception, exception.__traceback__)
611596

@@ -767,7 +752,7 @@ def _set_link_or_append_pointer(self, link: Union[SpanLink, _SpanPointer]) -> No
767752
except ValueError:
768753
self._links.append(link)
769754

770-
def finish_with_ancestors(self) -> None:
755+
def _finish_with_ancestors(self) -> None:
771756
"""Finish this span along with all (accessible) ancestors of this span.
772757
773758
This method is useful if a sudden program shutdown is required and finishing

ddtrace/appsec/_iast/__init__.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def wrapped_function(wrapped, instance, args, kwargs):
4646
_IAST_TO_BE_LOADED = True
4747
_iast_propagation_enabled = False
4848
_fork_handler_registered = False
49+
_iast_in_pytest_mode = False
4950

5051

5152
def _disable_iast_after_fork():
@@ -87,6 +88,15 @@ def _disable_iast_after_fork():
8788
from ddtrace.appsec._iast._iast_request_context_base import is_iast_request_enabled
8889
from ddtrace.appsec._iast._taint_tracking._context import clear_all_request_context_slots
8990

91+
# In pytest mode, always disable IAST in child processes to avoid segfaults
92+
# when tests create multiprocesses (e.g., for testing fork behavior)
93+
if _iast_in_pytest_mode:
94+
log.debug("IAST fork handler: Pytest mode detected, disabling IAST in child process")
95+
clear_all_request_context_slots()
96+
IAST_CONTEXT.set(None)
97+
asm_config._iast_enabled = False
98+
return
99+
90100
if not is_iast_request_enabled():
91101
# No active context - this is an early fork (web framework worker)
92102
# IAST can be safely initialized fresh in this child process
@@ -168,6 +178,7 @@ def enable_iast_propagation():
168178
"""Add IAST AST patching in the ModuleWatchdog"""
169179
# DEV: These imports are here to avoid _ast.ast_patching import in the top level
170180
# because they are slow and affect serverless startup time
181+
171182
if asm_config._iast_propagation_enabled:
172183
from ddtrace.appsec._iast._ast.ast_patching import _should_iast_patch
173184
from ddtrace.appsec._iast._loader import _exec_iast_patched_module
@@ -183,19 +194,30 @@ def enable_iast_propagation():
183194

184195

185196
def _iast_pytest_activation():
186-
global _iast_propagation_enabled
187-
if _iast_propagation_enabled:
197+
"""Configure IAST settings for pytest execution.
198+
199+
This function sets up IAST configuration but does NOT create a request context.
200+
Request contexts should be created per-test or per-request to avoid threading issues.
201+
202+
Also sets a global flag to indicate we're in pytest mode, which ensures IAST is
203+
disabled in forked child processes to prevent segfaults when tests use multiprocessing.
204+
"""
205+
global _iast_in_pytest_mode
206+
207+
if not asm_config._iast_enabled:
188208
return
189-
os.environ["DD_IAST_ENABLED"] = os.environ.get("DD_IAST_ENABLED") or "1"
209+
210+
# Mark that we're running in pytest mode
211+
# This flag is checked by the fork handler to disable IAST in child processes
212+
_iast_in_pytest_mode = True
213+
190214
os.environ["DD_IAST_REQUEST_SAMPLING"] = os.environ.get("DD_IAST_REQUEST_SAMPLING") or "100.0"
191215
os.environ["_DD_APPSEC_DEDUPLICATION_ENABLED"] = os.environ.get("_DD_APPSEC_DEDUPLICATION_ENABLED") or "false"
192216
os.environ["DD_IAST_VULNERABILITIES_PER_REQUEST"] = os.environ.get("DD_IAST_VULNERABILITIES_PER_REQUEST") or "1000"
193-
os.environ["DD_IAST_MAX_CONCURRENT_REQUESTS"] = os.environ.get("DD_IAST_MAX_CONCURRENT_REQUESTS") or "1000"
194217

195218
asm_config._iast_request_sampling = 100.0
196219
asm_config._deduplication_enabled = False
197220
asm_config._iast_max_vulnerabilities_per_requests = 1000
198-
asm_config._iast_max_concurrent_requests = 1000
199221
oce.reconfigure()
200222

201223

ddtrace/contrib/internal/aws_lambda/patch.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def _crash_flush(self, _, __):
103103

104104
current_span = tracer.current_span()
105105
if current_span is not None:
106-
current_span.finish_with_ancestors()
106+
current_span._finish_with_ancestors()
107107

108108
def _remove_alarm_signal(self):
109109
"""Removes the handler set for the signal `SIGALRM`."""

ddtrace/internal/packages.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,11 @@ def _root_module(path: Path) -> str:
142142
pass
143143

144144
# Bazel runfiles support: we assume that these paths look like
145-
# /some/path.runfiles/.../site-packages/<root_module>/...
146-
if any(p.suffix == ".runfiles" for p in path.parents):
147-
for s in path.parents:
148-
if s.parent.name == "site-packages":
149-
return s.name
145+
# /some/path.runfiles/<distribution_name>/site-packages/<root_module>/...
146+
# /usr/local/runfiles/<distribution_name>/site-packages/<root_module>/...
147+
for s in path.parents:
148+
if s.parent.name == "site-packages":
149+
return s.name
150150

151151
msg = f"Could not find root module for path {path}"
152152
raise ValueError(msg)
Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +0,0 @@
1-
from ddtrace.internal.utils.deprecations import DDTraceDeprecationWarning
2-
from ddtrace.vendor.debtcollector import deprecate
3-
4-
5-
def __getattr__(name):
6-
if name in set(
7-
[
8-
"ConfigException",
9-
"HttpConfig",
10-
"Hooks",
11-
"IntegrationConfig",
12-
]
13-
):
14-
deprecate(
15-
("%s.%s is deprecated" % (__name__, name)),
16-
removal_version="4.0.0", # TODO: update this to the correct version
17-
category=DDTraceDeprecationWarning,
18-
)
19-
if name == "ConfigException":
20-
from ddtrace.internal.settings.exceptions import ConfigException
21-
22-
return ConfigException
23-
elif name == "HttpConfig":
24-
from .http import HttpConfig
25-
26-
return HttpConfig
27-
elif name == "Hooks":
28-
from .._hooks import Hooks
29-
30-
return Hooks
31-
elif name == "IntegrationConfig":
32-
from .integration import IntegrationConfig
33-
34-
return IntegrationConfig
35-
raise AttributeError("'%s' has no attribute '%s'" % (__name__, name))

ddtrace/internal/settings/asm.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ class ASMConfig(DDConfig):
142142
+ r"ey[I-L][\w=-]+\.ey[I-L][\w=-]+(\.[\w.+\/=-]+)?|[\-]{5}BEGIN[a-z\s]+PRIVATE\sKEY"
143143
+ r"[\-]{5}[^\-]+[\-]{5}END[a-z\s]+PRIVATE\sKEY|ssh-rsa\s*[a-z0-9\/\.+]{100,}",
144144
)
145+
# We never use `asm_config._iast_max_concurrent_requests` directly,
146+
# but we define it so it can be reported through telemetry, since it’s used from the C files.
145147
_iast_max_concurrent_requests = DDConfig.var(
146148
int,
147149
IAST.DD_IAST_MAX_CONCURRENT_REQUESTS,

lib-injection/sources/requirements.csv

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
Dependency,Version Specifier,Python Version
2-
bytecode,>=0.17.0,python_version>='3.14.0'
3-
bytecode,>=0.16.0,python_version>='3.13.0'
4-
bytecode,>=0.15.1,python_version~='3.12.0'
5-
bytecode,>=0.14.0,python_version~='3.11.0'
6-
bytecode,>=0.13.0,python_version<'3.11'
2+
bytecode,">=0.17.0,<1",python_version>='3.14.0'
3+
bytecode,">=0.16.0,<1",python_version>='3.13.0'
4+
bytecode,">=0.15.1,<1",python_version~='3.12.0'
5+
bytecode,">=0.14.0,<1",python_version~='3.11.0'
6+
bytecode,">=0.13.0,<1",python_version<'3.11'
77
envier,~=0.6.1,
88
opentelemetry-api,">=1,<2",
99
wrapt,">=1,<3",

pyproject.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ classifiers = [
3535
"Programming Language :: Python :: 3.14",
3636
]
3737
dependencies = [
38-
"bytecode>=0.17.0; python_version>='3.14.0'",
39-
"bytecode>=0.16.0; python_version>='3.13.0'",
40-
"bytecode>=0.15.1; python_version~='3.12.0'",
41-
"bytecode>=0.14.0; python_version~='3.11.0'",
42-
"bytecode>=0.13.0; python_version<'3.11'",
38+
"bytecode>=0.17.0,<1; python_version>='3.14.0'",
39+
"bytecode>=0.16.0,<1; python_version>='3.13.0'",
40+
"bytecode>=0.15.1,<1; python_version~='3.12.0'",
41+
"bytecode>=0.14.0,<1; python_version~='3.11.0'",
42+
"bytecode>=0.13.0,<1; python_version<'3.11'",
4343
"envier~=0.6.1",
4444
"opentelemetry-api>=1,<2",
4545
"wrapt>=1,<3",
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
deprecations:
3+
- |
4+
tracing: ``Span.finished`` setter is deprecated, use ``Span.finish()`` method instead.
5+
- |
6+
tracing: ``Span.finish_with_ancestors()`` is deprecated with no alternative.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
upgrade:
3+
- |
4+
tracing: ``Span.finished`` setter was removed, please use ``Span.finish()`` method instead.
5+
- |
6+
tracing: ``Span.finish_with_ancestors`` was removed with no replacement.

0 commit comments

Comments
 (0)