Exemplo n.º 1
0
    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(
                    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(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
        def callback_wrapper(wrapped, instance, args, kwargs):

            if current_transaction():
                return wrapped(*args, **kwargs)

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

            request = transaction._nr_current_request()

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

            if not hasattr(request, '_nr_wait_function_trace'):
                return wrapped(*args, **kwargs)

            if not request._nr_wait_function_trace:
                return wrapped(*args, **kwargs)

            transaction.save_transaction()

            if request._nr_wait_function_trace:
                request._nr_wait_function_trace.__exit__(None, None, None)

            request._nr_wait_function_trace = None

            try:
                name = callable_name(wrapped)
                with FunctionTrace(transaction, name=name):
                    return wrapped(*args, **kwargs)

            except Exception:
                transaction.record_exception(*sys.exc_info())

                raise

            finally:
                if not request._nr_request_finished:
                    request._nr_wait_function_trace = FunctionTrace(
                        transaction,
                        name='Callback/Wait',
                        group='Python/Tornado')

                    request._nr_wait_function_trace.__enter__()
                    transaction.drop_transaction()

                elif not request.connection.stream.writing():
                    transaction.__exit__(None, None, None)
                    request._nr_transaction = None

                else:
                    request._nr_wait_function_trace = FunctionTrace(
                        transaction,
                        name='Request/Output',
                        group='Python/Tornado')

                    request._nr_wait_function_trace.__enter__()
                    transaction.drop_transaction()
async def waiter(asyncio, event, wait):
    with FunctionTrace(name='waiter1', terminal=True):
        event.set()

        # Block until the parent says to exit
        await wait.wait()

    with FunctionTrace(name='waiter2', terminal=True):
        pass

    await child()
Exemplo n.º 4
0
    def _test():
        transaction = current_transaction()
        transaction.queue_start = 1.0
        transaction._sampled = True

        with FunctionTrace('trace1') as trace_1:
            trace_1._add_agent_attribute('trace1_a', 'foobar')
            trace_1._add_agent_attribute('trace1_b', 'barbaz')
            with FunctionTrace('trace2') as trace_2:
                trace_2._add_agent_attribute('trace2_a', 'foobar')
                trace_2._add_agent_attribute('trace2_b', 'barbaz')
Exemplo n.º 5
0
    def close(self): 
        try: 
            with FunctionTrace(self.transaction, name='Finalize', 
                    group='Python/WSGI'): 
                if hasattr(self.generator, 'close'): 
                    name = callable_name(self.generator.close) 
                    with FunctionTrace(self.transaction, name): 
                        self.generator.close() 

        except: # Catch all 
            self.transaction.record_exception() 
            raise
Exemplo n.º 6
0
    def __call__(self, environ, start_response): 
        transaction = retrieve_current_transaction() 

        if transaction is None: 
            return self.wsgi_application(environ, start_response) 

        name = callable_name(self.wsgi_application) 

        with FunctionTrace(transaction, name='Application', 
                group='Python/WSGI'): 
            with FunctionTrace(transaction, name=name): 
                result = self.wsgi_application(environ, start_response) 

        return _WSGIApplicationIterable(transaction, result)
Exemplo n.º 7
0
def view_handler_wrapper(wrapped, instance, args, kwargs):
    transaction = current_transaction()

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

    try:
        view_callable = wrapped.__original_view__ or wrapped
    except AttributeError:
        view_callable = wrapped

    name = callable_name(view_callable)

    # set exception views to priority=1 so they won't take precedence over
    # the original view callable
    transaction.set_transaction_name(
        name, priority=1 if args and isinstance(args[0], Exception) else 2)

    with FunctionTrace(name, source=view_callable) as trace:
        try:
            return wrapped(*args, **kwargs)

        except:  # Catch all
            trace.notice_error(ignore=should_ignore, status_code=status_code)
            raise
Exemplo n.º 8
0
    def _wrapper(context, request):
        transaction = current_transaction()

        if not transaction:
            return wrapper(context, request)

        name = callable_name(view)

        with FunctionTrace(name=name, source=view) as tracer:
            try:
                return wrapper(context, request)
            finally:
                attr = instance.attr
                inst = getattr(request, '__view__', None)
                if inst is not None:
                    if attr:
                        handler = getattr(inst, attr)
                        name = callable_name(handler)
                        transaction.set_transaction_name(name, priority=2)
                        tracer.name = name
                        tracer.add_code_level_metrics(handler)
                    else:
                        method = getattr(inst, '__call__')
                        if method:
                            name = callable_name(method)
                            transaction.set_transaction_name(name, priority=2)
                            tracer.name = name
                            tracer.add_code_level_metrics(method)
    def _wrapper(context, request):
        transaction = current_transaction()

        if not transaction:
            return wrapper(context, request)

        name = callable_name(view)

        with FunctionTrace(name=name) as tracer:
            try:
                return wrapper(context, request)
            finally:
                attr = instance.attr
                if attr:
                    inst = getattr(request, '__view__', None)
                    if inst is not None:
                        name = callable_name(getattr(inst, attr))
                        transaction.set_transaction_name(name, priority=1)
                        tracer.name = name
                else:
                    inst = getattr(request, '__view__', None)
                    if inst is not None:
                        method = getattr(inst, '__call__')
                        if method:
                            name = callable_name(method)
                            transaction.set_transaction_name(name, priority=1)
                            tracer.name = name
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 wrapper(wrapped, instance, args, kwargs):
        transaction = current_transaction()

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

        transaction.name_transaction(name, priority=priority)

        with FunctionTrace(transaction, name=name):
            try:
                return wrapped(*args, **kwargs)

            except:  # Catch all
                # Python 2.5 doesn't allow *args before keywords.
                # See http://bugs.python.org/issue3473.
                exc_info = sys.exc_info()
                transaction.record_exception(exc_info[0],
                                             exc_info[1],
                                             exc_info[2],
                                             ignore_errors=[
                                                 'django.http:Http404',
                                                 'django.http.response:Http404'
                                             ])
                raise

            finally:
                exc_info = None
def callback_wrapper(wrapped, instance, args, kwargs):
    transaction = current_transaction()

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

    name = callable_name(wrapped)

    # Needs to be at a higher priority so that error handler processing
    # below will not override the web transaction being named after the
    # actual request handler.

    transaction.set_transaction_name(name, priority=2)

    with FunctionTrace(name=name, source=wrapped) as trace:
        try:
            return wrapped(*args, **kwargs)

        except:  # Catch all
            # In most cases this seems like it will never be invoked as
            # bottle will internally capture the exception before we
            # get a chance and rather than propagate the exception will
            # return it instead. This doesn't always seem to be the case
            # though when plugins are used, although that may depend on
            # the specific bottle version being used.
            trace.notice_error(status_code=status_code, ignore=should_ignore)
            raise
    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)

        with FunctionTrace(transaction, name=name):
            return wrapped(*args, **kwargs)
Exemplo n.º 14
0
def test_sentinel_exited_complete_root_exception():
    """
    This test forces a transaction to exit while it still has an active trace
    this causes an exception to be raised in TraceCache complete_root(). It
    verifies that the sentinel.exited property is set to true if an exception
    is raised in complete_root()
    """
    expected_error = "not the current trace"

    try:
        txn = None
        sentinel = None
        txn = BackgroundTask(application_instance(), "Parent")
        txn.__enter__()
        sentinel = txn.root_span
        trace = FunctionTrace("trace")
        trace.__enter__()
        txn.__exit__(None, None, None)
        assert False, "Did not raise exception"
    except RuntimeError as e:
        assert str(e) == expected_error
    finally:
        assert sentinel.exited
        # Make sure to exit properly so cleanup is performed
        trace.__exit__(None, None, None)
        txn.__exit__(None, None, None)
    def on_connection_close_wrapper(wrapped, instance, args, kwargs):
        transaction = current_transaction()

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

        handler = instance
        request = handler.request

        transaction = getattr(request, '_nr_transaction', None)

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

        transaction.save_transaction()

        if request._nr_wait_function_trace:
            request._nr_wait_function_trace.__exit__(None, None, None)

        name = callable_name(wrapped)

        try:
            with FunctionTrace(transaction, name):
                return wrapped(*args, **kwargs)

        except Exception:
            transaction.record_exception(*sys.exc_info())

        finally:
            transaction.__exit__(None, None, None)
        def wrapper(wrapped, instance, args, kwargs):
            transaction = current_transaction()

            def _wrapped(request, view_func, view_args, view_kwargs):
                # This strips the view handler wrapper before call.

                if hasattr(view_func, '_nr_last_object'):
                    view_func = view_func._nr_last_object

                return wrapped(request, view_func, view_args, view_kwargs)

            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.name_transaction(name, priority=2)
        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)
 def _inner():
     try:
         with FunctionTrace(transaction, name):
             result = yield from coro
         return result
     except:
         transaction.record_exception(ignore_errors=should_ignore)
         raise
Exemplo n.º 19
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()
Exemplo n.º 20
0
    def start_trace(self):
        if not self.transaction._sent_start:
            self.transaction._sent_start = time.time()

        if not self.response_trace:
            self.response_trace = FunctionTrace(
                    name='Response', group='Python/WSGI')
            self.response_trace.__enter__()
Exemplo n.º 21
0
def test_async_trace_overlapping_children():
    parent_trace = FunctionTrace('parent')

    with parent_trace:
        child_trace_1 = FunctionTrace('child_1', parent=parent_trace)
        child_trace_2 = FunctionTrace('child_2', parent=parent_trace)

        child_trace_1.__enter__()
        child_trace_2.__enter__()
        time.sleep(0.01)
        child_trace_1.__exit__(None, None, None)
        child_trace_2.__exit__(None, None, None)

    assert parent_trace.start_time < child_trace_1.start_time
    assert child_trace_1.start_time < child_trace_2.start_time
    assert child_trace_1.end_time < child_trace_2.end_time
    assert child_trace_2.end_time < parent_trace.end_time
Exemplo n.º 22
0
def _nr_wrapper_WSGIContainer___call__no_body_(wrapped, instance,
        args, kwargs):

    # This variant of the WSGIContainer.__call__() wrapper is used when
    # being used direct with HTTPServer and it is believed that we are
    # being called for a HTTP request where there is no request content.
    # There should be no transaction associated with the Tornado request
    # object and also no current active transaction. Create the
    # transaction but if it is None then it means recording of
    # transactions is not enabled then do not need to do anything.

    def _params(request, *args, **kwargs):
        return request

    request = _params(*args, **kwargs)

    transaction = initiate_request_monitoring(request)

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

    # Call the original method in a trace object to give better context
    # in transaction traces. It should only every return an exception is
    # situation where application was being shutdown so finalize the
    # transaction on any error.

    transaction.set_transaction_name(request.uri, 'Uri', priority=1)

    try:
        with FunctionTrace(transaction, name='Request/Process',
                group='Python/Tornado'):
            result = wrapped(*args, **kwargs)

    except:  # Catch all
        finalize_request_monitoring(request, *sys.exc_info())
        raise

    else:
        # In the case of the response completing immediately or an
        # exception occuring, then finish() should have been called on
        # the request already. We can't just exit the transaction in the
        # finish() call however as will need to still pop back up
        # through the above function trace. So if it has been flagged
        # that it is finished, which Tornado does by setting the request
        # object in the connection to None, then we exit the transaction
        # here. Otherwise we setup a function trace to track wait time
        # for deferred and suspend monitoring.

        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 result
Exemplo n.º 23
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
Exemplo n.º 24
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)
async def trace_in_cache_txn_active(asyncio, bg):
    event = asyncio.Event()

    with BackgroundTask(application(), 'fg'):
        with FunctionTrace('fg') as _:
            task = asyncio.ensure_future(bg(event))
        await event.wait()

    return task
Exemplo n.º 26
0
        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)
Exemplo n.º 27
0
    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)
    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)
def test_trace_after_end_of_transaction(caplog):
    end_of_transaction()
    with FunctionTrace("foobar"):
        pass

    error_messages = [
        record for record in caplog.records if record.levelno >= logging.ERROR
    ]
    assert not error_messages
    def render_wrapper(wrapped, instance, args, kwargs):
        transaction = current_transaction()

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

        name = callable_name(wrapped)
        with FunctionTrace(transaction, name=name):
            return wrapped(*args, **kwargs)