Skip to content

Commit e0435b5

Browse files
brettlangdongithub-actions[bot]
authored andcommitted
fix(tracing): preserve generator return values in @tracer.wrap() decorator (#13784)
The @tracer.wrap() decorator was not properly preserving return values from generator functions. When a wrapped generator function returned a value, the StopIteration exception's value attribute was None instead of the actual returned value. This fix ensures that generator return values are properly captured and propagated through the StopIteration exception by storing the return value from 'yield from' and returning it after the tracing context exits. ## 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 - [ ] 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) (cherry picked from commit 4b87ee8)
1 parent e0e451c commit e0435b5

File tree

3 files changed

+28
-1
lines changed

3 files changed

+28
-1
lines changed

ddtrace/_trace/tracer.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,8 @@ def func_wrapper(*args, **kwargs):
775775
)
776776

777777
with self.trace(span_name, service=service, resource=resource, span_type=span_type):
778-
yield from f(*args, **kwargs)
778+
return_value = yield from f(*args, **kwargs)
779+
return return_value
779780

780781
return func_wrapper
781782

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
fixes:
3+
- |
4+
tracing: This fix resolves an issue where the ``@tracer.wrap()`` decorator failed to preserve return values from generator functions, causing ``StopIteration.value`` to be ``None`` instead of the actual returned value.

tests/tracer/test_tracer.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,28 @@ def wrapper():
355355
"visible to the caller"
356356
)
357357

358+
def test_tracer_wrap_generator_with_return_value(self):
359+
@self.tracer.wrap()
360+
def iter_signals():
361+
for i in range(10):
362+
yield i
363+
return 10
364+
365+
with self.trace("root") as span:
366+
signals = iter_signals()
367+
while True:
368+
try:
369+
# DEV: We don't need the return value
370+
next(signals)
371+
except StopIteration as e:
372+
assert e.value == 10
373+
span.set_metric("num_signals", e.value)
374+
break
375+
376+
self.assert_span_count(2)
377+
root_span = self.get_root_span()
378+
root_span.assert_matches(name="root", metrics={"num_signals": 10})
379+
358380
def test_tracer_disabled(self):
359381
self.tracer.enabled = True
360382
with self.trace("foo") as s:

0 commit comments

Comments
 (0)