Example #1
0
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(name=name):
            return _wrapped(*args, **kwargs)

    return FunctionWrapper(middleware, wrapper)
Example #2
0
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
Example #3
0
    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(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_middleware(wrapped, instance, args, kwargs):
    result = wrapped(*args, **kwargs)

    dispatch_func = getattr(result, "dispatch_func", None)
    name = dispatch_func and callable_name(dispatch_func)

    return FunctionTraceWrapper(result, name=name)
def grpc_web_transaction(wrapped, instance, args, kwargs):
    rpc_event, behavior = _bind_transaction_args(*args, **kwargs)
    behavior_name = callable_name(behavior)

    call_details = (getattr(rpc_event, 'call_details', None)
                    or getattr(rpc_event, 'request_call_details', None))

    metadata = (getattr(rpc_event, 'invocation_metadata', None)
                or getattr(rpc_event, 'request_metadata', None))

    host = port = None
    if call_details:
        try:
            host, port = call_details.host.split(b':', 1)
        except Exception:
            pass

        request_path = call_details.method

    return WebTransactionWrapper(wrapped,
                                 name=behavior_name,
                                 request_path=request_path,
                                 host=host,
                                 port=port,
                                 headers=metadata)(*args, **kwargs)
Example #6
0
def route_naming_wrapper(wrapped, instance, args, kwargs):

    with ContextOf(request=bind_request(*args, **kwargs)):
        transaction = current_transaction()
        if transaction:
            transaction.set_transaction_name(callable_name(wrapped), priority=2)
        return wrapped(*args, **kwargs)
def test_span_event_error_attributes_observed(trace_type, args):

    error = ValueError("whoops")

    exact_agents = {
        'error.class': callable_name(error),
        'error.message': 'whoops',
    }

    # Verify errors are not recorded since record_exception is not called
    rollups = [('Errors/all', None)] + _span_event_metrics

    @dt_enabled
    @validate_transaction_metrics(
            'test_span_event_error_attributes_observed',
            background_task=True,
            rollup_metrics=rollups)
    @validate_span_events(
        count=1,
        exact_agents=exact_agents,)
    @background_task(name='test_span_event_error_attributes_observed')
    def _test():
        try:
            with trace_type(*args):
                raise error
        except:
            pass

    _test()
def test_span_event_error_attributes_record_exception(trace_type, args):

    _settings = {
        'distributed_tracing.enabled': True,
        'span_events.enabled': True,
    }

    error = ValueError("whoops")

    exact_agents = {
        'error.class': callable_name(error),
        'error.message': 'whoops',
    }

    @override_application_settings(_settings)
    @validate_transaction_metrics(
            'test_span_event_error_attributes_record_exception',
            background_task=True,
            rollup_metrics=_span_event_metrics)
    @validate_span_events(
        count=1,
        exact_agents=exact_agents,)
    @background_task(name='test_span_event_error_attributes_record_exception')
    def _test():
        transaction = current_transaction()
        transaction._sampled = True

        with trace_type(*args):
            try:
                raise ValueError("whoops")
            except:
                record_exception()

    _test()
def _nr_wrapper_APIView_dispatch_(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)
    request_method = request.method.lower()

    if request_method in view.http_method_names:
        handler = getattr(view, request_method, view.http_method_not_allowed)
    else:
        handler = view.http_method_not_allowed

    view_func_callable_name = getattr(view, '_nr_view_func_callable_name', None)
    if view_func_callable_name:
        if handler == view.http_method_not_allowed:
            name = '%s.%s' % (view_func_callable_name,
                    'http_method_not_allowed')
        else:
            name = '%s.%s' % (view_func_callable_name, request_method)
    else:
        name = callable_name(handler)

    transaction.set_transaction_name(name)

    with FunctionTrace(transaction, name):
        return wrapped(*args, **kwargs)
    def close(self):
        if self.closed:
            return

        if self.response_trace:
            self.response_trace.__exit__(None, None, None)
            self.response_trace = None

        try:
            with FunctionTrace(self.transaction,
                               name='Finalize',
                               group='Python/WSGI'):

                if isinstance(self.generator, _WSGIApplicationMiddleware):
                    self.generator.close()

                elif hasattr(self.generator, 'close'):
                    name = callable_name(self.generator.close)
                    with FunctionTrace(self.transaction, name):
                        self.generator.close()

        except:  # Catch all
            self.transaction.__exit__(*sys.exc_info())
            raise

        else:
            self.transaction.__exit__(None, None, None)
            self.transaction._sent_end = time.time()

        finally:
            self.closed = True
Example #11
0
def _nr_wrapper_RequestHandler__execute_(wrapped, instance, args, kwargs):
    # Prior to Tornado 3.1, the calling of the handler request method
    # was performed from within RequestHandler._execute(). Any prepare()
    # method was called immediately and could not be a coroutine. For
    # later versions of Tornado, if the prepare() method is a coroutine
    # and the future cannot be completed immediately, then the handler
    # request method will be called from _execute_method() instead when
    # prepare() completes.

    handler = instance
    request = handler.request

    # Check to see if we are being called within the context of any sort
    # of transaction. If we aren't, then we don't bother doing anything and
    # just call the wrapped function.

    transaction = retrieve_current_transaction()

    if transaction is None:
        return wrapped(*args, **kwargs)

    # If the method isn't one of the supported ones, then we expect the
    # wrapped method to raise an exception for HTTPError(405). Name the
    # transaction after the wrapped method first so it is used if that
    # occurs.

    name = callable_name(wrapped)
    transaction.set_transaction_name(name)

    if request.method not in handler.SUPPORTED_METHODS:
        return wrapped(*args, **kwargs)

    # Otherwise we name the transaction after the handler function that
    # should end up being executed for the request. We don't create a
    # function trace node at this point as that is handled by the fact
    # that we wrapped the exposed methods from the wrapper for the
    # constructor of the request handler.

    name = callable_name(getattr(handler, request.method.lower()))
    transaction.set_transaction_name(name)

    # Call the original RequestHandler._execute(). So long as the
    # prepare() method is not a coroutine which doesn't complete
    # straight away, then the actual handler function handler should
    # also be called at this point.

    return wrapped(*args, **kwargs)
def _nr_wrapper_handler_(wrapped, instance, args, kwargs):
    transaction = current_transaction()

    if transaction is None:
        return wrapped(*args, **kwargs)

    name = callable_name(wrapped)
    view_class = getattr(wrapped, 'view_class', None)
    if view_class:
        try:
            method = args[0].method.lower()
            name = callable_name(view_class) + '.' + method
        except:
            pass
    transaction.set_transaction_name(name, priority=3)

    return function_trace(name=name)(wrapped)(*args, **kwargs)
Example #13
0
    def close(self):
        # Call close() on the iterable as required by the
        # WSGI specification.

        if hasattr(self.iterable, 'close'):
            name = callable_name(self.iterable.close)
            with FunctionTrace(name):
                self.iterable.close()
Example #14
0
def wrap_parse(wrapped, instance, args, kwargs):
    transaction = current_transaction()
    if transaction is None:
        return wrapped(*args, **kwargs)

    transaction.set_transaction_name(callable_name(wrapped), "GraphQL", priority=10)
    with ErrorTrace(ignore=ignore_graphql_duplicate_exception):
        return wrapped(*args, **kwargs)
Example #15
0
def _nr_wrapper_IOLoop_add_callback_(wrapped, instance, args, kwargs):
    transaction = retrieve_current_transaction()

    if transaction is None:
        return wrapped(*args, **kwargs)

    name = callable_name(wrapped)

    def _args(callback, *args, **kwargs):
        return callback

    callback = _args(*args, **kwargs)

    params = dict(callback=callable_name(callback))

    with FunctionTrace(transaction, name, params=params, terminal=True):
        return wrapped(*args, **kwargs)
def test_uvicorn_200(port, app):
    @validate_transaction_metrics(callable_name(app))
    @raise_background_exceptions()
    @wait_for_background_threads()
    def response():
        return urlopen("http://localhost:%d" % port)

    assert response().status == 200
Example #17
0
def _nr_wrapper_web_requesthandler_init(wrapped, instance, args, kwargs):
    transaction = current_transaction()

    if transaction is None:
        return wrapped(*args, **kwargs)

    name = callable_name(instance)
    transaction.set_transaction_name(name, priority=1)
    return wrapped(*args, **kwargs)
Example #18
0
    def transaction_aware(wrapped, instance, args, kwargs):
        # Variables from the outer scope are not assignable in a closure,
        # so we use a mutable object to hold the transaction, so we can
        # change it if we need to.
        inner_transaction = transaction[0]

        if inner_transaction is not None:
            # Callback run outside the main thread must not affect the cache
            if inner_transaction.thread_id != current_thread_id():
                return fxn(*args, **kwargs)

        if inner_transaction is not None and inner_transaction._is_finalized:
            inner_transaction = None
            transaction[0] = None

        with TransactionContext(inner_transaction):
            if inner_transaction is None:
                # A transaction will be None for fxns scheduled on the ioloop
                # not associated with a transaction.
                ret = fxn(*args, **kwargs)

            elif should_trace is False:
                try:
                    ret = fxn(*args, **kwargs)
                except:
                    record_exception(sys.exc_info())
                    wrapped._nr_recorded_exception = True
                    raise

            else:
                name = callable_name(fxn_for_name)
                with FunctionTrace(inner_transaction, name=name) as ft:

                    try:
                        ret = fxn(*args, **kwargs)
                    except:
                        record_exception(sys.exc_info())
                        wrapped._nr_recorded_exception = True
                        raise

                    # Coroutines are wrapped in lambdas when they are
                    # scheduled. See tornado.gen.Runner.run(). In this
                    # case, we don't know the name until the function
                    # is run. We only know it then because we pass
                    # out the name as an attribute on the result.
                    # We update the name now.

                    if hasattr(fxn, '_nr_coroutine_name'):
                        ft.name = fxn._nr_coroutine_name

        # If decrementing the ref count in Runner.run() takes it to 0, then
        # we need to end the transaction here.

        if inner_transaction:
            possibly_finalize_transaction(inner_transaction)

        return ret
        def callback_wrapper(wrapped, instance, args, kwargs):
            name = callable_name(wrapped)

            transaction = current_transaction(active_only=False)

            if transaction and (transaction.ignore_transaction or
                    transaction.stopped):
                return wrapped(*args, **kwargs)
            elif transaction:
                with FunctionTrace(name=name):
                    return wrapped(*args, **kwargs)
            else:
                if hasattr(channel, '_nr_disable_txn_tracing'):
                    return wrapped(*args, **kwargs)

                # Keyword arguments are unknown since this is a user
                # defined callback
                exchange = 'Unknown'
                routing_key = None
                headers = None
                reply_to = None
                correlation_id = None
                unknown_kwargs = False
                if not kwargs:
                    method, properties = args[1:3]
                    exchange = method.exchange or 'Default'
                    routing_key = getattr(method, 'routing_key', None)
                    if properties is not None:
                        headers = getattr(properties, 'headers', None)
                        reply_to = getattr(properties, 'reply_to', None)
                        correlation_id = getattr(
                                properties, 'correlation_id', None)
                else:
                    unknown_kwargs = True

                with MessageTransaction(
                        application=application_instance(),
                        library='RabbitMQ',
                        destination_type='Exchange',
                        destination_name=exchange,
                        routing_key=routing_key,
                        headers=headers,
                        queue_name=queue,
                        reply_to=reply_to,
                        correlation_id=correlation_id) as mt:

                    # Improve transaction naming
                    _new_txn_name = 'RabbitMQ/Exchange/%s/%s' % (exchange,
                            name)
                    mt.set_transaction_name(_new_txn_name, group='Message')

                    # Record that something went horribly wrong
                    if unknown_kwargs:
                        m = mt._transaction_metrics.get(KWARGS_ERROR, 0)
                        mt._transaction_metrics[KWARGS_ERROR] = m + 1

                    return wrapped(*args, **kwargs)
Example #20
0
def _requesthandler_function_trace(wrapped, instance, args, kwargs):
    # Use this function tracer when a function you want to trace is called
    # synchronously from a function that is already in the transaction, such as
    # web.RequestHandler._execute.
    transaction = retrieve_current_transaction()

    name = callable_name(wrapped)
    with FunctionTrace(transaction, name=name):
        return wrapped(*args, **kwargs)
Example #21
0
    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')
Example #22
0
def _nr_aiohttp_initial_class_transaction_name_(wrapped, instance, args,
                                                kwargs):
    transaction = current_transaction()

    if not transaction:
        return wrapped(*args, **kwargs)

    name = callable_name(instance)
    transaction.set_transaction_name(name, priority=1)
    return wrapped(*args, **kwargs)
Example #23
0
def _nr_aiohttp_view_wrapper_(wrapped, instance, args, kwargs):
    transaction = current_transaction()

    if not transaction:
        return wrapped(*args, **kwargs)

    name = callable_name(wrapped)
    transaction.set_transaction_name(name, priority=1)

    return function_trace(name=name)(wrapped)(*args, **kwargs)
Example #24
0
def _nr_wrapper_handler_(wrapped, instance, args, kwargs):
    transaction = current_transaction()

    if transaction is None:
        return wrapped(*args, **kwargs)

    name = callable_name(wrapped)
    transaction.set_transaction_name(name, priority=3)

    return function_trace(name=name)(wrapped)(*args, **kwargs)
def _nr_wrapper_convert_exception_to_response_(wrapped, instance, args,
                                               kwargs):
    def _bind_params(original_middleware, *args, **kwargs):
        return original_middleware

    original_middleware = _bind_params(*args, **kwargs)
    converted_middleware = wrapped(*args, **kwargs)
    name = callable_name(original_middleware)

    return _nr_wrap_converted_middleware_(converted_middleware, name)
def _sanic_app_init(wrapped, instance, args, kwargs):
    result = wrapped(*args, **kwargs)

    error_handler = getattr(instance, 'error_handler')
    if hasattr(error_handler, 'response'):
        instance.error_handler.response = error_response(
            error_handler.response)
    if hasattr(error_handler, 'add'):
        error_handler.add = _nr_sanic_error_handlers(error_handler.add)

    router = getattr(instance, 'router')
    if hasattr(router, 'add'):
        router.add = _nr_sanic_router_add(router.add)
    if hasattr(router, 'get'):
        # Cache the callable_name on the router.get
        callable_name(router.get)
        router.get = _nr_sanic_router_get(router.get)

    return result
Example #27
0
    def __call__(self, *args, **kwargs):
        rollup = []
        rollup.append('Datastore/all')
        rollup.append('Datastore/%s/all' %
                self._nr_dbapi2_module._nr_database_product)

        with FunctionTrace(callable_name(self.__wrapped__),
                terminal=True, rollup=rollup, source=self.__wrapped__):
            return self.__connection_wrapper__(self.__wrapped__(
                    *args, **kwargs), self._nr_dbapi2_module, (args, kwargs))
Example #28
0
def _nr_wrapper_api_view_decorator_(wrapped, instance, args, kwargs):
    def _bind_params(func, *args, **kwargs):
        return func

    func = _bind_params(*args, **kwargs)
    view = wrapped(*args, **kwargs)

    view.cls._nr_view_func_callable_name = callable_name(func)

    return view
Example #29
0
def wrap_middleware(wrapped, instance, args, kwargs):
    transaction = current_transaction()
    if transaction is None:
        return wrapped(*args, **kwargs)

    name = callable_name(wrapped)
    transaction.set_transaction_name(name, "GraphQL", priority=12)
    with FunctionTrace(name, source=wrapped):
        with ErrorTrace(ignore=ignore_graphql_duplicate_exception):
            return wrapped(*args, **kwargs)
Example #30
0
def _nr_sanic_router_get(wrapped, instance, args, kwargs):
    # Rename all transactions that generate an exception in the router get
    try:
        return wrapped(*args, **kwargs)
    except Exception:
        transaction = current_transaction()
        if transaction:
            name = callable_name(wrapped)
            transaction.set_transaction_name(name, priority=2)
        raise