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
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)
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
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')
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
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
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