Example #1
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
Example #2
0
    def _close():
        transaction = resume_request_monitoring(request)

        if transaction is None:
            return

        # Force a function trace to record the fact that the socket
        # connection was closed due to client disconnection.

        with FunctionTrace(transaction,
                           name='Request/Close',
                           group='Python/Tornado'):
            pass

        # We finish up the transaction and nothing else should occur.

        finalize_request_monitoring(request)
Example #3
0
def _nr_wrapper_HTTPConnection__on_request_body_(wrapped, instance, args,
                                                 kwargs):

    # Called when there was a request body and it has now all been
    # read in and buffered ready to call the request handler.

    assert instance is not None

    connection = instance
    request = connection._request

    # Wipe out our temporary callback for being notified that the
    # connection is being closed before content is read.

    connection.stream._nr_close_callback = None

    # Restore any transaction which may have been suspended.

    transaction = resume_request_monitoring(request)

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

    # Now call the orginal wrapped function.

    try:
        result = wrapped(*args, **kwargs)

    except:  # Catch all
        # There should never be an error from wrapped function but
        # in case there is, try finalizing transaction.

        finalize_request_monitoring(request)
        raise

    else:
        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
Example #4
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 #5
0
def _nr_wrapper_RequestHandler_on_connection_close(wrapped, instance, args,
                                                   kwargs):

    # The RequestHandler.on_connection_close() method is called when the
    # client closes the connection prematurely before the request had
    # been completed. The callback itself wasn't registered at a point
    # where there was any request tracking so there shouldn't be any
    # active transaction when this is called. We track the call of the
    # wrapped method and then finalize the whole transaction.

    transaction = retrieve_current_transaction()

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

    handler = instance
    request = handler.request

    transaction = resume_request_monitoring(request)

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

    name = callable_name(wrapped)

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

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

    else:
        finalize_request_monitoring(request)

        return result
Example #6
0
def _nr_wrapper_HTTPConnection__finish_request(wrapped, instance, args,
                                               kwargs):

    # Normally called when the request is all complete meaning that we
    # have to finalize our own transaction. We may actually enter here
    # with the transaction already being the current one.

    connection = instance
    request = connection._request

    transaction = retrieve_request_transaction(request)

    # The wrapped function could be called more than once. If it is then
    # the transaction should already have been completed. In this case
    # the transaction should be None. To be safe also check whether the
    # request itself was already flagged as finished. If transaction was
    # the same as the current transaction the following check would have
    # just marked it as finished again, but this first check will cover
    # where the current transaction is for some reason different.

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

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

    # Deal now with the possibility that the transaction is already the
    # current active transaction.

    if transaction == retrieve_current_transaction():
        finish_request_monitoring(request)

        return wrapped(*args, **kwargs)

    # If we enter here with an active transaction and it isn't the one
    # we expect, then not sure what we should be doing, so simply
    # return. This should hopefully never occur.

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

    # Not the current active transaction and so we need to try and
    # resume the transaction associated with the request.

    transaction = resume_request_monitoring(request)

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

    finish_request_monitoring(request)

    try:
        result = wrapped(*args, **kwargs)

    except:  # Catch all
        # There should never be an error from wrapped function but
        # in case there is, try finalizing transaction.

        finalize_request_monitoring(request, *sys.exc_info())
        raise

    finalize_request_monitoring(request)

    return result
Example #7
0
def _nr_wrapper_RequestHandler_finish_(wrapped, instance, args, kwargs):
    # The RequestHandler.finish() method will either be called explicitly
    # by the user, but called also be called automatically by Tornado.
    # It is possible that it can be called twice so it is necessary to
    # protect against that.

    handler = instance
    request = handler.request

    # Bail out out if we think the request as a whole has been completed.

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

    # Call wrapped method straight away if request object it is being
    # called on is not even associated with a transaction. If we were in
    # a running transaction we still want to record the call though.
    # This will occur when calling finish on another request, but the
    # target request wasn't monitored.

    transaction = retrieve_request_transaction(request)

    active_transaction = retrieve_current_transaction()

    if transaction is None:
        if active_transaction is not None:
            name = callable_name(wrapped)

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

        else:
            return wrapped(*args, **kwargs)

    # If we have an active transaction, we we need to consider two
    # possiblities. The first is where the current running transaction
    # doesn't match that bound to the request. For this case it would be
    # where from within one transaction there is an attempt to call
    # finish() on a distinct web request which was being monitored. The
    # second is where finish() is being called for the current request.

    if active_transaction is not None:
        if transaction != active_transaction:
            # For this case we need to suspend the current running
            # transaction and call ourselves again. When it returns
            # we need to restore things back the way they were.
            # We still trace the call in the running transaction
            # though so the fact that it called finish on another
            # request is apparent.

            name = callable_name(wrapped)

            with FunctionTrace(active_transaction, name):
                try:
                    active_transaction.drop_transaction()

                    return _nr_wrapper_RequestHandler_finish_(
                        wrapped, instance, args, kwargs)

                finally:
                    active_transaction.save_transaction()

        else:
            # For this case we just trace the call.

            name = callable_name(wrapped)

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

    # Attempt to resume the transaction, calling the wrapped method
    # straight away if there isn't one. Otherwise trace the call.

    transaction = resume_request_monitoring(request)

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

    try:
        name = callable_name(wrapped)

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

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

    else:
        if not request.connection.stream.writing():
            finalize_request_monitoring(request)

        else:
            suspend_request_monitoring(request, name='Request/Output')

        return result