def wrap_view_handler(wrapped, priority=3): # Ensure we don't wrap the view handler more than once. This # looks like it may occur in cases where the resolver is # called recursively. We flag that view handler was wrapped # using the '_nr_django_view_handler' attribute. if hasattr(wrapped, '_nr_django_view_handler'): return wrapped name = callable_name(wrapped) def wrapper(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) transaction.set_transaction_name(name, priority=priority) with FunctionTrace(transaction, name=name): try: return wrapped(*args, **kwargs) except: # Catch all transaction.record_exception(ignore_errors=should_ignore) raise result = FunctionWrapper(wrapped, wrapper) result._nr_django_view_handler = True return result
def wrap_view_handler(mapped_view): if hasattr(mapped_view, '_nr_wrapped'): return mapped_view else: wrapped = FunctionWrapper(mapped_view, view_handler_wrapper) wrapped._nr_wrapped = True return wrapped
def wrap_handle_uncaught_exception(middleware): # Wrapper to be applied to handler called when exceptions # propagate up to top level from middleware. Records the # time spent in the handler as separate function node. Names # the web transaction after the name of the handler if not # already named at higher priority and capture further # errors in the handler. name = callable_name(middleware) def wrapper(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) def _wrapped(request, resolver, exc_info): transaction.set_transaction_name(name, priority=1) transaction.record_exception(*exc_info) try: return wrapped(request, resolver, exc_info) except: # Catch all transaction.record_exception(*sys.exc_info()) raise with FunctionTrace(transaction, name=name): return _wrapped(*args, **kwargs) return FunctionWrapper(middleware, 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 wrapper(wrapped): # The middleware if a class method would already be # bound at this point, so is safe to determine the name # when it is being wrapped rather than on each # invocation. name = callable_name(wrapped) def wrapper(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) before = (transaction.name, transaction.group) with FunctionTrace(transaction, name=name): try: return wrapped(*args, **kwargs) finally: # We want to name the transaction after this # middleware but only if the transaction wasn't # named from within the middleware itself explicity. after = (transaction.name, transaction.group) if before == after: transaction.set_transaction_name(name, priority=2) return FunctionWrapper(wrapped, wrapper)
def 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) # 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, callback_wrapper(request)) return wrapped(fn)
def wrap_view_dispatch(wrapped): # Wrapper to be applied to dispatcher for class based views. def wrapper(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) def _args(request, *args, **kwargs): return request view = instance request = _args(*args, **kwargs) # We can't intercept the delegated view handler when it # is looked up by the dispatch() method so we need to # duplicate the lookup mechanism. if request.method.lower() in view.http_method_names: handler = getattr(view, request.method.lower(), view.http_method_not_allowed) else: handler = view.http_method_not_allowed name = callable_name(handler) transaction.set_transaction_name(name, priority=4) with FunctionTrace(transaction, name=name): return wrapped(*args, **kwargs) return FunctionWrapper(wrapped, wrapper)
def instrument_pyramid_config_views(module): # Location of the ViewDeriver class changed from pyramid.config to # pyramid.config.views so check if present before trying to update. if hasattr(module, 'ViewDeriver'): wrap_out_function(module, 'ViewDeriver.__call__', wrap_view_handler) elif hasattr(module, 'Configurator'): wrap_out_function(module, 'Configurator._derive_view', wrap_view_handler) if hasattr(module, 'DefaultViewMapper'): module.DefaultViewMapper.map_class_requestonly = FunctionWrapper( module.DefaultViewMapper.map_class_requestonly, default_view_mapper_wrapper) module.DefaultViewMapper.map_class_native = FunctionWrapper( module.DefaultViewMapper.map_class_native, default_view_mapper_wrapper)
def wrap_view_dispatch(wrapped): # Wrapper to be applied to dispatcher for class based views. def wrapper(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) def _args(request, *args, **kwargs): return request view = instance request = _args(*args, **kwargs) # We can't intercept the delegated view handler when it # is looked up by the dispatch() method so we need to # duplicate the lookup mechanism. if request.method.lower() in view.http_method_names: handler = getattr(view, request.method.lower(), view.http_method_not_allowed) else: handler = view.http_method_not_allowed name = callable_name(handler) # The priority to be used when naming the transaction is # bit tricky. If the transaction name is already that of # the class based view, but not the method, then we want # the name of the method to override. This can occur # where the class based view was registered directly in # urls.py as the view handler. In this case we use the # priority of 5, matching what would be used by the view # handler so that it can override the transaction name. # # If however the transaction name is unrelated, we # preferably don't want it overridden. This can happen # where the class based view was invoked explicitly # within an existing view handler. In this case we use # the priority of 4 so it will not override the view # handler name where used as the transaction name. priority = 4 if transaction.group == 'Function': if transaction.name == callable_name(view): priority = 5 transaction.set_transaction_name(name, priority=priority) with FunctionTrace(transaction, name=name): return wrapped(*args, **kwargs) return FunctionWrapper(wrapped, wrapper)
def wrap_template_block(wrapped): def wrapper(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) with FunctionTrace(transaction, name=instance.name, group='Template/Block'): return wrapped(*args, **kwargs) return FunctionWrapper(wrapped, wrapper)
def wrapper_GearmanWorker_register_task(wrapped, instance, args, kwargs): def _bind_params(task, callback_function, *args, **kwargs): return task, callback_function, args, kwargs # This applies a wrapper around the task function at the point that # it is registered. This is so we can later wrap execution with a # function trace and catch and record any exceptions in the task # function. task, callback_function, _args, _kwargs = _bind_params(*args, **kwargs) callback_function = FunctionWrapper(callback_function, wrapper_callback_function) return wrapped(task, callback_function, *_args, **_kwargs)
def wrap_url_resolver(wrapped): # Wrap URL resolver. If resolver returns valid result then # wrap the view handler returned. The type of the result # changes across Django versions so need to check and adapt # as necessary. For a 404 then a user supplied 404 handler # or the default 404 handler should get later invoked and # transaction should be named after that. name = callable_name(wrapped) def wrapper(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) if hasattr(transaction, '_nr_django_url_resolver'): return wrapped(*args, **kwargs) # Tag the transaction so we know when we are in the top # level call to the URL resolver as don't want to show # the inner ones as would be one for each url pattern. transaction._nr_django_url_resolver = True def _wrapped(path): # XXX This can raise a Resolver404. If this is not dealt # with, is this the source of our unnamed 404 requests. with FunctionTrace(transaction, name=name, label=path): result = wrapped(path) if type(result) is tuple: callback, callback_args, callback_kwargs = result result = (wrap_view_handler(callback, priority=5), callback_args, callback_kwargs) else: result.func = wrap_view_handler(result.func, priority=5) return result try: return _wrapped(*args, **kwargs) finally: del transaction._nr_django_url_resolver return FunctionWrapper(wrapped, wrapper)
def wrap_url_resolver_nnn(wrapped, priority=1): # Wrapper to be applied to the URL resolver for errors. name = callable_name(wrapped) def wrapper(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) with FunctionTrace(transaction, name=name): callback, param_dict = wrapped(*args, **kwargs) return (wrap_view_handler(callback, priority=priority), param_dict) return FunctionWrapper(wrapped, wrapper)
def wrapper(wrapped): # The middleware if a class method would already be # bound at this point, so is safe to determine the name # when it is being wrapped rather than on each # invocation. name = callable_name(wrapped) def wrapper(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) with FunctionTrace(transaction, name=name): return wrapped(*args, **kwargs) return FunctionWrapper(wrapped, wrapper)
def wrap_url_reverse(wrapped): # Wrap the URL resolver reverse lookup. Where the view # handler is passed in we need to strip any instrumentation # wrapper to ensure that it doesn't interfere with the # lookup process. Technically this may now not be required # as we have improved the proxying in the object wrapper, # but do it just to avoid any potential for problems. def wrapper(wrapped, instance, args, kwargs): def execute(viewname, *args, **kwargs): if hasattr(viewname, '_nr_last_object'): viewname = viewname._nr_last_object return wrapped(viewname, *args, **kwargs) return execute(*args, **kwargs) return FunctionWrapper(wrapped, wrapper)