def ExternalTraceWrapper(wrapped, library, url, method=None): def dynamic_wrapper(wrapped, instance, args, kwargs): wrapper = async_wrapper(wrapped) if not wrapper: parent = current_trace() if not parent: return wrapped(*args, **kwargs) else: parent = None if callable(url): if instance is not None: _url = url(instance, *args, **kwargs) else: _url = url(*args, **kwargs) else: _url = url if callable(method): if instance is not None: _method = method(instance, *args, **kwargs) else: _method = method(*args, **kwargs) else: _method = method trace = ExternalTrace(library, _url, _method, parent=parent) if wrapper: return wrapper(wrapped, trace)(*args, **kwargs) with trace: return wrapped(*args, **kwargs) def literal_wrapper(wrapped, instance, args, kwargs): wrapper = async_wrapper(wrapped) if not wrapper: parent = current_trace() if not parent: return wrapped(*args, **kwargs) else: parent = None trace = ExternalTrace(library, url, method, parent=parent) wrapper = async_wrapper(wrapped) if wrapper: return wrapper(wrapped, trace)(*args, **kwargs) with trace: return wrapped(*args, **kwargs) if callable(url) or callable(method): return FunctionWrapper(wrapped, dynamic_wrapper) return FunctionWrapper(wrapped, literal_wrapper)
def ExternalTraceWrapper(wrapped, library, url, method=None): def dynamic_wrapper(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) if callable(url): if instance is not None: _url = url(instance, *args, **kwargs) else: _url = url(*args, **kwargs) else: _url = url if callable(method): if instance is not None: _method = method(instance, *args, **kwargs) else: _method = method(*args, **kwargs) else: _method = method trace = ExternalTrace(transaction, library, _url, _method) proxy = async_proxy(wrapped) if proxy: return proxy(wrapped(*args, **kwargs), TraceContext(trace)) with trace: return wrapped(*args, **kwargs) def literal_wrapper(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) trace = ExternalTrace(transaction, library, url, method) proxy = async_proxy(wrapped) if proxy: return proxy(wrapped(*args, **kwargs), TraceContext(trace)) with trace: return wrapped(*args, **kwargs) if callable(url) or callable(method): return FunctionWrapper(wrapped, dynamic_wrapper) return FunctionWrapper(wrapped, literal_wrapper)
def TransactionNameWrapper(wrapped, name=None, group=None, priority=None): def dynamic_wrapper(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) if callable(name): if instance is not None: _name = name(instance, *args, **kwargs) else: _name = name(*args, **kwargs) elif name is None: _name = callable_name(wrapped) else: _name = name if callable(group): if instance is not None: _group = group(instance, *args, **kwargs) else: _group = group(*args, **kwargs) else: _group = group transaction.set_transaction_name(_name, _group, priority) return wrapped(*args, **kwargs) def literal_wrapper(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) _name = name or callable_name(wrapped) transaction.set_transaction_name(_name, group, priority) return wrapped(*args, **kwargs) if callable(name) or callable(group): return FunctionWrapper(wrapped, dynamic_wrapper) return FunctionWrapper(wrapped, literal_wrapper)
def DatastoreTraceWrapper(wrapped, product, target, operation): def _nr_datastore_trace_wrapper_(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) if callable(product): if instance is not None: _product = product(instance, *args, **kwargs) else: _product = product(*args, **kwargs) else: _product = product if callable(target): if instance is not None: _target = target(instance, *args, **kwargs) else: _target = target(*args, **kwargs) else: _target = target if callable(operation): if instance is not None: _operation = operation(instance, *args, **kwargs) else: _operation = operation(*args, **kwargs) else: _operation = operation with DatastoreTrace(transaction, _product, _target, _operation): return wrapped(*args, **kwargs) return FunctionWrapper(wrapped, _nr_datastore_trace_wrapper_)
def MemcacheTraceWrapper(wrapped, command): def _nr_wrapper_memcache_trace_(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) if callable(command): if instance is not None: _command = command(instance, *args, **kwargs) else: _command = command(*args, **kwargs) else: _command = command trace = MemcacheTrace(transaction, _command) proxy = async_proxy(wrapped) if proxy: return proxy(wrapped(*args, **kwargs), TraceContext(trace)) with trace: return wrapped(*args, **kwargs) return FunctionWrapper(wrapped, _nr_wrapper_memcache_trace_)
def wrap_add_tween(wrapped, instance, args, kwargs): def _bind_params(name, factory, *_args, **_kwargs): return name, factory, _args, _kwargs name, factory, args, kwargs = _bind_params(*args, **kwargs) factory = FunctionWrapper(factory, wrap_tween_factory) return wrapped(name, factory, *args, **kwargs)
def wrap_template_block(wrapped): def wrapper(wrapped, instance, args, kwargs): return FunctionTraceWrapper(wrapped, name=instance.name, group='Template/Block')(*args, **kwargs) 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) 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 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 MemcacheTraceWrapper(wrapped, command): def _nr_wrapper_memcache_trace_(wrapped, instance, args, kwargs): wrapper = async_wrapper(wrapped) if not wrapper: parent = current_trace() if not parent: return wrapped(*args, **kwargs) else: parent = None if callable(command): if instance is not None: _command = command(instance, *args, **kwargs) else: _command = command(*args, **kwargs) else: _command = command trace = MemcacheTrace(_command, parent=parent) if wrapper: return wrapper(wrapped, trace)(*args, **kwargs) with trace: return wrapped(*args, **kwargs) return FunctionWrapper(wrapped, _nr_wrapper_memcache_trace_)
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 DatabaseTraceWrapper(wrapped, sql, dbapi2_module=None): def _nr_database_trace_wrapper_(wrapped, instance, args, kwargs): wrapper = async_wrapper(wrapped) if not wrapper: parent = current_trace() if not parent: return wrapped(*args, **kwargs) else: parent = None if callable(sql): if instance is not None: _sql = sql(instance, *args, **kwargs) else: _sql = sql(*args, **kwargs) else: _sql = sql trace = DatabaseTrace(_sql, dbapi2_module, parent=parent, source=wrapped) if wrapper: # pylint: disable=W0125,W0126 return wrapper(wrapped, trace)(*args, **kwargs) with trace: return wrapped(*args, **kwargs) return FunctionWrapper(wrapped, _nr_database_trace_wrapper_)
def DatabaseTraceWrapper(wrapped, sql, dbapi2_module=None): def _nr_database_trace_wrapper_(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) if callable(sql): if instance is not None: _sql = sql(instance, *args, **kwargs) else: _sql = sql(*args, **kwargs) else: _sql = sql trace = DatabaseTrace(transaction, _sql, dbapi2_module) proxy = async_proxy(wrapped) if proxy: return proxy(wrapped(*args, **kwargs), TraceContext(trace)) with trace: return wrapped(*args, **kwargs) return FunctionWrapper(wrapped, _nr_database_trace_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 ExternalTraceWrapper(wrapped, library, url, method=None): return_value = return_value_fn(wrapped) def dynamic_wrapper(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) if callable(url): if instance is not None: _url = url(instance, *args, **kwargs) else: _url = url(*args, **kwargs) else: _url = url if callable(method): if instance is not None: _method = method(instance, *args, **kwargs) else: _method = method(*args, **kwargs) else: _method = method trace = ExternalTrace(transaction, library, _url, _method) return return_value(trace, lambda: wrapped(*args, **kwargs)) def literal_wrapper(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) trace = ExternalTrace(transaction, library, url, method) return return_value(trace, lambda: wrapped(*args, **kwargs)) if callable(url) or callable(method): return FunctionWrapper(wrapped, dynamic_wrapper) return FunctionWrapper(wrapped, literal_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 MessageTraceWrapper(wrapped, library, operation, destination_type, destination_name, params={}): return_value = return_value_fn(wrapped) def _nr_message_trace_wrapper_(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) if callable(library): if instance is not None: _library = library(instance, *args, **kwargs) else: _library = library(*args, **kwargs) else: _library = library if callable(operation): if instance is not None: _operation = operation(instance, *args, **kwargs) else: _operation = operation(*args, **kwargs) else: _operation = operation if callable(destination_type): if instance is not None: _destination_type = destination_type(instance, *args, **kwargs) else: _destination_type = destination_type(*args, **kwargs) else: _destination_type = destination_type if callable(destination_name): if instance is not None: _destination_name = destination_name(instance, *args, **kwargs) else: _destination_name = destination_name(*args, **kwargs) else: _destination_name = destination_name trace = MessageTrace(transaction, _library, _operation, _destination_type, _destination_name, params={}) return return_value(trace, lambda: wrapped(*args, **kwargs)) return FunctionWrapper(wrapped, _nr_message_trace_wrapper_)
def MessageTraceWrapper(wrapped, library, operation, destination_type, destination_name, params={}): def _nr_message_trace_wrapper_(wrapped, instance, args, kwargs): wrapper = async_wrapper(wrapped) if not wrapper: parent = current_trace() if not parent: return wrapped(*args, **kwargs) else: parent = None if callable(library): if instance is not None: _library = library(instance, *args, **kwargs) else: _library = library(*args, **kwargs) else: _library = library if callable(operation): if instance is not None: _operation = operation(instance, *args, **kwargs) else: _operation = operation(*args, **kwargs) else: _operation = operation if callable(destination_type): if instance is not None: _destination_type = destination_type(instance, *args, **kwargs) else: _destination_type = destination_type(*args, **kwargs) else: _destination_type = destination_type if callable(destination_name): if instance is not None: _destination_name = destination_name(instance, *args, **kwargs) else: _destination_name = destination_name(*args, **kwargs) else: _destination_name = destination_name trace = MessageTrace(_library, _operation, _destination_type, _destination_name, params={}, parent=parent) if wrapper: return wrapper(wrapped, trace)(*args, **kwargs) with trace: return wrapped(*args, **kwargs) return FunctionWrapper(wrapped, _nr_message_trace_wrapper_)
def ErrorTraceWrapper(wrapped, ignore_errors=[]): def wrapper(wrapped, instance, args, kwargs): parent = current_trace() if parent is None: return wrapped(*args, **kwargs) with ErrorTrace(ignore_errors, parent=parent): return wrapped(*args, **kwargs) return FunctionWrapper(wrapped, wrapper)
def ErrorTraceWrapper(wrapped, ignore_errors=[]): def wrapper(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) with ErrorTrace(transaction, ignore_errors): return wrapped(*args, **kwargs) return FunctionWrapper(wrapped, wrapper)
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 if hasattr(wrapped, "view_class"): name = callable_name(wrapped.view_class) else: 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(name=name, source=wrapped): try: return wrapped(*args, **kwargs) except: # Catch all exc_info = sys.exc_info() try: # Store exc_info on the request to check response code # prior to reporting args[0]._nr_exc_info = exc_info except: notice_error(exc_info) raise result = FunctionWrapper(wrapped, wrapper) result._nr_django_view_handler = True return result
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(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): with FunctionTrace(name=name): 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_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) handler = resolve_view_handler(view, request) 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(name=name, source=handler): 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)
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 DatabaseTraceWrapper(wrapped, sql, dbapi2_module=None): def _nr_database_trace_wrapper_(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) if callable(sql): if instance is not None: _sql = sql(instance, *args, **kwargs) else: _sql = sql(*args, **kwargs) else: _sql = sql with DatabaseTrace(transaction, _sql, dbapi2_module): return wrapped(*args, **kwargs) return FunctionWrapper(wrapped, _nr_database_trace_wrapper_)
def GraphQLResolverTraceWrapper(wrapped): def _nr_graphql_trace_wrapper_(wrapped, instance, args, kwargs): wrapper = async_wrapper(wrapped) if not wrapper: parent = current_trace() if not parent: return wrapped(*args, **kwargs) else: parent = None trace = GraphQLResolverTrace(parent=parent, source=wrapped) if wrapper: # pylint: disable=W0125,W0126 return wrapper(wrapped, trace)(*args, **kwargs) with trace: return wrapped(*args, **kwargs) return FunctionWrapper(wrapped, _nr_graphql_trace_wrapper_)