Repository URL to install this package:
|
Version:
2.68.0.50 ▾
|
import sys
import logging
from newrelic.agent import (wrap_function_wrapper, FunctionTrace,
callable_name, FunctionWrapper)
from . import (retrieve_transaction_request, retrieve_request_transaction,
request_finished, suspend_request_monitoring, resume_request_monitoring,
finalize_request_monitoring, record_exception,
retrieve_current_transaction)
_logger = logging.getLogger(__name__)
module_stack_context = None
def _nr_stack_context_wrap_wrapped_(request):
def _nr_stack_context_function_wrapper_(wrapped, instance, args, kwargs):
# We can come in here with either an active transaction
# or a request with a transaction bound to it. If there
# is an active transaction then call the wrapped function
# within function trace and return immediately.
transaction = retrieve_current_transaction()
if transaction is not None:
name = callable_name(wrapped)
with FunctionTrace(transaction, name=name):
return wrapped(*args, **kwargs)
# For the case of a request with a transaction bound to
# it, we need to resume the transaction and then call it.
# As we resumed the transaction, need to handle
# suspending or finalizing it.
transaction = resume_request_monitoring(request)
if transaction is None:
return wrapped(*args, **kwargs)
try:
name = callable_name(wrapped)
with FunctionTrace(transaction, name=name):
return wrapped(*args, **kwargs)
except: # Catch all.
record_exception(transaction, sys.exc_info())
raise
finally:
if not request_finished(request):
suspend_request_monitoring(request, name='Callback/Wait')
elif not request.connection.stream.writing():
finalize_request_monitoring(request)
else:
suspend_request_monitoring(request, name='Request/Output')
return _nr_stack_context_function_wrapper_
def _nr_stack_context_wrap_wrapper_(wrapped, instance, args, kwargs):
def _args(fn, *args, **kwargs):
return fn
transaction = retrieve_current_transaction()
if not transaction:
return wrapped(*args, **kwargs)
request = retrieve_transaction_request(transaction)
if request is None:
return wrapped(*args, **kwargs)
fn = _args(*args, **kwargs)
# We need to filter out certain out types of wrapped functions.
# Tornado 3.1 doesn't use _StackContextWrapper and checks for a
# '_wrapped' attribute instead which makes this a bit more fragile.
if hasattr(module_stack_context, '_StackContextWrapper'):
if (fn is None or
fn.__class__ is module_stack_context._StackContextWrapper):
return fn
else:
if fn is None or hasattr(fn, '_wrapped'):
return fn
fn = FunctionWrapper(fn, _nr_stack_context_wrap_wrapped_(request))
return wrapped(fn)
def instrument_tornado_stack_context(module):
global module_stack_context
module_stack_context = module
wrap_function_wrapper(module, 'wrap', _nr_stack_context_wrap_wrapper_)