Skip to content

Commit 888209f

Browse files
fix(debugging): make probe instances hashable [backport #13309 to 2.21] (#13319)
Backport 3c2015e from #13309 to 2.21. Probes are mutable but have an identity that allows them to be hashed. We make sure that probe instances are hashable. This in turns makes code objects where probes are injected hashable and usable for lookups. ## 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) Co-authored-by: Brett Langdon <[email protected]>
1 parent ebb9846 commit 888209f

File tree

4 files changed

+35
-7
lines changed

4 files changed

+35
-7
lines changed

ddtrace/debugging/_probe/model.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ class CaptureLimits:
6565
DEFAULT_CAPTURE_LIMITS = CaptureLimits()
6666

6767

68+
# NOTE: Probe dataclasses are mutable, but have an identity, so can be hashed.
69+
# When defining a probe class, the `eq` parameter of the `dataclass` decorator
70+
# should be set to `False` to allow the `__hash__` method from the base Probe
71+
# class to be used.
72+
73+
6874
@dataclass
6975
class Probe(abc.ABC):
7076
__context_creator__ = False
@@ -193,12 +199,12 @@ class MetricProbeMixin(AbstractProbeMixIn):
193199
value: Optional[DDExpression]
194200

195201

196-
@dataclass
202+
@dataclass(eq=False)
197203
class MetricLineProbe(Probe, LineLocationMixin, MetricProbeMixin, ProbeConditionMixin):
198204
pass
199205

200206

201-
@dataclass
207+
@dataclass(eq=False)
202208
class MetricFunctionProbe(Probe, FunctionLocationMixin, TimingMixin, MetricProbeMixin, ProbeConditionMixin):
203209
pass
204210

@@ -246,13 +252,13 @@ class LogProbeMixin(AbstractProbeMixIn):
246252
limits: CaptureLimits = field(compare=False)
247253

248254

249-
@dataclass
255+
@dataclass(eq=False)
250256
class LogLineProbe(Probe, LineLocationMixin, LogProbeMixin, ProbeConditionMixin, RateLimitMixin):
251257
def is_global_rate_limited(self) -> bool:
252258
return self.take_snapshot
253259

254260

255-
@dataclass
261+
@dataclass(eq=False)
256262
class LogFunctionProbe(Probe, FunctionLocationMixin, TimingMixin, LogProbeMixin, ProbeConditionMixin, RateLimitMixin):
257263
def is_global_rate_limited(self) -> bool:
258264
return self.take_snapshot
@@ -263,7 +269,7 @@ class SpanProbeMixin:
263269
pass
264270

265271

266-
@dataclass
272+
@dataclass(eq=False)
267273
class SpanFunctionProbe(Probe, FunctionLocationMixin, SpanProbeMixin, ProbeConditionMixin):
268274
__context_creator__: bool = field(default=True, init=False, repr=False, compare=False)
269275

@@ -291,12 +297,12 @@ class SpanDecorationMixin:
291297
decorations: List[SpanDecoration]
292298

293299

294-
@dataclass
300+
@dataclass(eq=False)
295301
class SpanDecorationLineProbe(Probe, LineLocationMixin, SpanDecorationMixin):
296302
pass
297303

298304

299-
@dataclass
305+
@dataclass(eq=False)
300306
class SpanDecorationFunctionProbe(Probe, FunctionLocationMixin, TimingMixin, SpanDecorationMixin):
301307
pass
302308

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
fixes:
3+
- |
4+
dynamic instrumentation: fix incompatibility between code origin and
5+
dynamic instrumentation probe on exit span functions.

tests/debugging/probe/test_model.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,17 @@ def test_mutability():
4343
before.update(after)
4444

4545
assert before == after
46+
47+
48+
def test_probe_hash():
49+
probe = create_log_line_probe(
50+
probe_id="test_mutability",
51+
version=2,
52+
condition=DDExpression(dsl="True", callable=dd_compile(True)),
53+
source_file="foo",
54+
line=1,
55+
template="",
56+
segments=[],
57+
)
58+
59+
assert hash(probe)

tests/debugging/test_debugger.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ def simple_debugger_test(probe, func):
5858

5959
d.add_probes(probe)
6060

61+
# Check that we can still hash the code object
62+
assert hash(func.__code__)
63+
6164
try:
6265
func()
6366
except Exception:

0 commit comments

Comments
 (0)