Fix the trace function for async functions. (#7872)

Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>
pull/7888/head
Patrick Cloke 2020-07-17 13:32:01 -04:00 committed by GitHub
parent 1ec2961b3b
commit d1d5fa66e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 25 deletions

1
changelog.d/7872.bugfix Normal file
View File

@ -0,0 +1 @@
Fix a long standing bug where the tracing of async functions with opentracing was broken.

View File

@ -733,37 +733,54 @@ def trace(func=None, opname=None):
_opname = opname if opname else func.__name__
@wraps(func)
def _trace_inner(*args, **kwargs):
if opentracing is None:
return func(*args, **kwargs)
if inspect.iscoroutinefunction(func):
scope = start_active_span(_opname)
scope.__enter__()
@wraps(func)
async def _trace_inner(*args, **kwargs):
if opentracing is None:
return await func(*args, **kwargs)
try:
result = func(*args, **kwargs)
if isinstance(result, defer.Deferred):
def call_back(result):
scope.__exit__(None, None, None)
return result
def err_back(result):
with start_active_span(_opname) as scope:
try:
return await func(*args, **kwargs)
except Exception:
scope.span.set_tag(tags.ERROR, True)
raise
else:
# The other case here handles both sync functions and those
# decorated with inlineDeferred.
@wraps(func)
def _trace_inner(*args, **kwargs):
if opentracing is None:
return func(*args, **kwargs)
scope = start_active_span(_opname)
scope.__enter__()
try:
result = func(*args, **kwargs)
if isinstance(result, defer.Deferred):
def call_back(result):
scope.__exit__(None, None, None)
return result
def err_back(result):
scope.span.set_tag(tags.ERROR, True)
scope.__exit__(None, None, None)
return result
result.addCallbacks(call_back, err_back)
else:
scope.__exit__(None, None, None)
return result
result.addCallbacks(call_back, err_back)
return result
else:
scope.__exit__(None, None, None)
return result
except Exception as e:
scope.__exit__(type(e), None, e.__traceback__)
raise
except Exception as e:
scope.__exit__(type(e), None, e.__traceback__)
raise
return _trace_inner