Пример #1
0
def instrument_django_template(module):

    # Wrap methods for rendering of Django templates. The name
    # of the method changed in between Django versions so need
    # to check for which one we have. The name of the function
    # trace node is taken from the name of the template. This
    # should be a relative path with the template loader
    # uniquely associating it with a specific template library.
    # Therefore do not need to worry about making it absolute as
    # meaning should be known in the context of the specific
    # Django site.

    def template_name(template, *args):
        return template.name

    if hasattr(module.Template, '_render'):
        wrap_function_trace(module, 'Template._render',
                name=template_name, group='Template/Render')
    else:
        wrap_function_trace(module, 'Template.render',
                name=template_name, group='Template/Render')

    # Register template tags used for manual insertion of RUM
    # header and footer.
    #
    # TODO This can now be installed as a separate tag library
    # so should possibly look at deprecating this automatic
    # way of doing things.

    library = module.Library()
    library.simple_tag(newrelic_browser_timing_header)
    library.simple_tag(newrelic_browser_timing_footer)

    module.libraries['django.templatetags.newrelic'] = library
Пример #2
0
def instrument_django_template(module):

    # Wrap methods for rendering of Django templates. The name
    # of the method changed in between Django versions so need
    # to check for which one we have. The name of the function
    # trace node is taken from the name of the template. This
    # should be a relative path with the template loader
    # uniquely associating it with a specific template library.
    # Therefore do not need to worry about making it absolute as
    # meaning should be known in the context of the specific
    # Django site.

    def template_name(template, *args):
        return template.name

    if hasattr(module.Template, '_render'):
        wrap_function_trace(module, 'Template._render',
                name=template_name, group='Template/Render')
    else:
        wrap_function_trace(module, 'Template.render',
                name=template_name, group='Template/Render')

    # Register template tags used for manual insertion of RUM
    # header and footer.
    #
    # TODO This can now be installed as a separate tag library
    # so should possibly look at deprecating this automatic
    # way of doing things.

    library = module.Library()
    library.simple_tag(newrelic_browser_timing_header)
    library.simple_tag(newrelic_browser_timing_footer)

    module.libraries['django.templatetags.newrelic'] = library
def instrument_starlette_exceptions(module):
    wrap_function_trace(module, "ExceptionMiddleware.__call__")

    wrap_function_wrapper(module, "ExceptionMiddleware.http_exception",
                          wrap_exception_handler)

    wrap_function_wrapper(module, "ExceptionMiddleware.add_exception_handler",
                          wrap_add_exception_handler)
Пример #4
0
def instrument_pymongo_mongo_client(module):
    # Must name function explicitly as pymongo overrides the
    # __getattr__() method in a way that breaks introspection.

    rollup = ('Datastore/all', 'Datastore/MongoDB/all')

    wrap_function_trace(module, 'MongoClient.__init__',
            name='%s:MongoClient.__init__' % module.__name__,
            terminal=True, rollup=rollup)
Пример #5
0
def hook_motor():
    for class_name, methods in _motor_classes.items():
        thing = getattr(motor.motor_asyncio, class_name)
        if thing is not None:
            for method in methods:
                if hasattr(thing, method):
                    wrap_function_trace(motor.motor_asyncio,
                                        '%s.%s' % (class_name, method),
                                        name='motor: %s.%s' %
                                        (class_name, method))
def instrument_starlette_middleware_errors(module):
    wrap_function_trace(module, "ServerErrorMiddleware.__call__")

    wrap_function_wrapper(module, "ServerErrorMiddleware.__init__",
                          wrap_server_error_handler)

    wrap_function_wrapper(module, "ServerErrorMiddleware.error_response",
                          wrap_exception_handler)

    wrap_function_wrapper(module, "ServerErrorMiddleware.debug_response",
                          wrap_exception_handler)
Пример #7
0
def instrument_tornado_httpserver(module):
    if hasattr(module, 'HTTPConnection'):
        # The HTTPConnection class only existed prior to Tornado 4.0.

        wrap_function_wrapper(module, 'HTTPConnection._on_headers',
                              _nr_wrapper_HTTPConnection__on_headers_)
        wrap_function_wrapper(module, 'HTTPConnection._on_request_body',
                              _nr_wrapper_HTTPConnection__on_request_body_)
        wrap_function_wrapper(module, 'HTTPConnection._finish_request',
                              _nr_wrapper_HTTPConnection__finish_request)

    if hasattr(module.HTTPRequest, '_parse_mime_body'):
        wrap_function_trace(module, 'HTTPRequest._parse_mime_body')
Пример #8
0
def instrument_flask_app(module):
    wrap_wsgi_application(module, 'Flask.wsgi_app',
            framework=framework_details())

    wrap_function_wrapper(module, 'Flask.add_url_rule',
            _nr_wrapper_Flask_add_url_rule_input_)

    if hasattr(module.Flask, 'endpoint'):
        wrap_function_wrapper(module, 'Flask.endpoint',
                _nr_wrapper_Flask_endpoint_)

    wrap_function_wrapper(module, 'Flask.handle_http_exception',
            _nr_wrapper_Flask_handle_http_exception_)

    # Use the same wrapper for initial user exception processing and
    # fallback for unhandled exceptions.

    if hasattr(module.Flask, 'handle_user_exception'):
        wrap_function_wrapper(module, 'Flask.handle_user_exception',
                _nr_wrapper_Flask_handle_exception_)

    wrap_function_wrapper(module, 'Flask.handle_exception',
            _nr_wrapper_Flask_handle_exception_)

    # The _register_error_handler() method was only introduced in
    # Flask version 0.7.0.

    if hasattr(module.Flask, '_register_error_handler'):
        wrap_function_wrapper(module, 'Flask._register_error_handler',
                _nr_wrapper_Flask__register_error_handler_)

    # Different before/after methods were added in different versions.
    # Check for the presence of everything before patching.

    if hasattr(module.Flask, 'try_trigger_before_first_request_functions'):
        wrap_function_wrapper(module,
                'Flask.try_trigger_before_first_request_functions',
                _nr_wrapper_Flask_try_trigger_before_first_request_functions_)
        wrap_function_wrapper(module, 'Flask.before_first_request',
                _nr_wrapper_Flask_before_first_request_)

    if hasattr(module.Flask, 'preprocess_request'):
        wrap_function_trace(module, 'Flask.preprocess_request')
        wrap_function_wrapper(module, 'Flask.before_request',
                _nr_wrapper_Flask_before_request_)

    if hasattr(module.Flask, 'process_response'):
        wrap_function_trace(module, 'Flask.process_response')
        wrap_function_wrapper(module, 'Flask.after_request',
                _nr_wrapper_Flask_after_request_)

    if hasattr(module.Flask, 'do_teardown_request'):
        wrap_function_trace(module, 'Flask.do_teardown_request')
        wrap_function_wrapper(module, 'Flask.teardown_request',
                _nr_wrapper_Flask_teardown_request_)

    if hasattr(module.Flask, 'do_teardown_appcontext'):
        wrap_function_trace(module, 'Flask.do_teardown_appcontext')
        wrap_function_wrapper(module, 'Flask.teardown_appcontext',
                _nr_wrapper_Flask_teardown_appcontext_)
Пример #9
0
def instrument_bottle(module):
    global module_bottle
    module_bottle = module

    framework_details = ('Bottle', getattr(module, '__version__'))

    if hasattr(module.Bottle, 'wsgi'):  # version >= 0.9
        wrap_wsgi_application(module,
                              'Bottle.wsgi',
                              framework=framework_details)
    elif hasattr(module.Bottle, '__call__'):  # version < 0.9
        wrap_wsgi_application(module,
                              'Bottle.__call__',
                              framework=framework_details)

    if (hasattr(module, 'Route')
            and hasattr(module.Route, '_make_callback')):  # version >= 0.10
        wrap_out_function(module, 'Route._make_callback',
                          output_wrapper_Route_make_callback)
    elif hasattr(module.Bottle, '_match'):  # version >= 0.9
        wrap_out_function(module, 'Bottle._match', output_wrapper_Bottle_match)
    elif hasattr(module.Bottle, 'match_url'):  # version < 0.9
        wrap_out_function(module, 'Bottle.match_url',
                          output_wrapper_Bottle_match)

    wrap_object_attribute(module, 'Bottle.error_handler',
                          proxy_Bottle_error_handler)

    if hasattr(module, 'auth_basic'):
        wrap_function_wrapper(module, 'auth_basic', wrapper_auth_basic)

    if hasattr(module, 'SimpleTemplate'):
        wrap_function_trace(module, 'SimpleTemplate.render')

    if hasattr(module, 'MakoTemplate'):
        wrap_function_trace(module, 'MakoTemplate.render')

    if hasattr(module, 'CheetahTemplate'):
        wrap_function_trace(module, 'CheetahTemplate.render')

    if hasattr(module, 'Jinja2Template'):
        wrap_function_trace(module, 'Jinja2Template.render')

    if hasattr(module, 'SimpleTALTemplate'):
        wrap_function_trace(module, 'SimpleTALTemplate.render')
Пример #10
0
def instrument_tornado_ioloop(module):
    wrap_function_trace(module, 'IOLoop.add_handler')
    wrap_function_trace(module, 'IOLoop.add_timeout')

    wrap_function_wrapper(module, 'IOLoop.add_callback',
                          _nr_wrapper_IOLoop_add_callback_)

    if hasattr(module.IOLoop, 'add_future'):
        wrap_function_wrapper(module, 'IOLoop.add_future',
                              _nr_wrapper_IOLoop_add_future_)

    if hasattr(module, 'PollIOLoop'):
        wrap_function_trace(module, 'PollIOLoop.add_handler')
        wrap_function_trace(module, 'PollIOLoop.add_timeout')

        wrap_function_wrapper(module, 'PollIOLoop.add_callback',
                              _nr_wrapper_IOLoop_add_callback_)

        wrap_function_trace(module, 'PollIOLoop.add_callback_from_signal')
Пример #11
0
def hook_discord():
    # The normal New Relic API doesn't work here, let's replace the existing `Command.invoke` function with a version
    # that wraps it in a background task transaction
    async def _command_invoke(self, *args, **kwargs):
        # If there's already a running transaction, don't start a new one. New Relic doesn't handle coroutines very
        # well.
        transaction = current_transaction()
        if transaction:
            return await self._invoke(*args, **kwargs)

        with newrelic.agent.BackgroundTask(application,
                                           name='command: %s' %
                                           self.qualified_name):
            await self._invoke(*args, **kwargs)

    commands.Command._invoke = commands.Command.invoke
    commands.Command.invoke = _command_invoke

    # We can just hook these the simple way
    wrap_function_trace(asyncio, 'wait_for', name='asyncio: wait_for')
def instrument_weberror_reporter(module):
    def smtp_url(reporter, *args, **kwargs):
        return 'smtp://' + reporter.smtp_server

    wrap_external_trace(module, 'EmailReporter.report', 'weberror', smtp_url)
    wrap_function_trace(module, 'EmailReporter.report')

    wrap_function_trace(module, 'LogReporter.report')
    wrap_function_trace(module, 'FileReporter.report')
Пример #13
0
def _nr_wrapper_RequestHandler___init___(wrapped, instance, args, kwargs):
    # In this case we are actually wrapping the instance method on an
    # actual instance of a handler class rather than the class itself.
    # This is so we can wrap any derived version of this method when
    # it has been overridden in a handler class.

    wrap_function_wrapper(instance, 'on_connection_close',
                          _nr_wrapper_RequestHandler_on_connection_close)

    wrap_function_trace(instance, 'prepare')

    if hasattr(instance, 'on_finish'):
        wrap_function_trace(instance, 'on_finish')

    handler = instance

    for name in handler.SUPPORTED_METHODS:
        name = name.lower()
        if hasattr(handler, name):
            wrap_function_trace(instance, name)

    return wrapped(*args, **kwargs)
Пример #14
0
def instrument_gearman_client(module):
    wrap_function_trace(module, 'GearmanClient.submit_job')
    wrap_function_trace(module, 'GearmanClient.submit_multiple_jobs')
    wrap_function_trace(module, 'GearmanClient.submit_multiple_requests')
    wrap_function_trace(module, 'GearmanClient.wait_until_jobs_accepted')
    wrap_function_trace(module, 'GearmanClient.wait_until_jobs_completed')
    wrap_function_trace(module, 'GearmanClient.get_job_status')
    wrap_function_trace(module, 'GearmanClient.get_job_statuses')
    wrap_function_trace(module,
                        'GearmanClient.wait_until_job_statuses_received')
def instrument_weberror_errormiddleware(module):

    wrap_function_trace(module, 'handle_exception')
Пример #16
0
def instrument_tornado_simple_httpclient(module):
    wrap_function_trace(module, 'SimpleAsyncHTTPClient.fetch')
Пример #17
0
def instrument_flask_templating(module):
    wrap_function_trace(module, 'render_template')
    wrap_function_trace(module, 'render_template_string')
Пример #18
0
def instrument_cherrypy__cpreqbody(module):
    wrap_function_trace(module, 'process_multipart')
    wrap_function_trace(module, 'process_multipart_form_data')
Пример #19
0
def instrument_tornado_httpserver(module):

    def on_headers_wrapper(wrapped, instance, args, kwargs):
        assert instance is not None

        connection = instance

        # Check to see if we are being called within the context of any
        # sort of transaction. If we are, then we don't bother doing
        # anything and just call the wrapped function. This should not
        # really ever occur but check anyway.

        transaction = current_transaction()

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

        # Execute the wrapped function as we are only going to do
        # something after it has been called. The function doesn't
        # return anything.

        wrapped(*args, **kwargs)

        # Check to see if the connection has already been closed or the
        # request finished. The connection can be closed where request
        # content length was too big.

        if connection.stream.closed():
            return

        if connection._request_finished:
            return

        # Check to see if have already associated a transaction with
        # the request, because if we have, even if not finished, then
        # do not need to do anything.

        request = connection._request

        if request is None:
            return

        if hasattr(request, '_nr_transaction'):
            return

        # Always use the default application specified in the agent
        # configuration.

        application = application_instance()

        # We need to fake up a WSGI like environ dictionary with the
        # key bits of information we need.

        environ = request_environment(application, request)

        # Now start recording the actual web transaction. Bail out
        # though if turns out that recording transactions is not
        # enabled.

        transaction = WebTransaction(application, environ)

        if not transaction.enabled:
            return

        transaction.__enter__()

        request._nr_transaction = transaction

        request._nr_wait_function_trace = None
        request._nr_request_finished = False

        # Add a callback variable to the connection object so we can
        # be notified when the connection is closed before all content
        # has been read.

        def _close():
            transaction.save_transaction()

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

            finally:
                request._nr_wait_function_trace = None

            transaction.__exit__(None, None, None)
            request._nr_transaction = None

        connection.stream._nr_close_callback = _close

        # Name transaction initially after the wrapped function so
        # that if connection dropped before request content read,
        # then don't get metric grouping issues with it being named
        # after the URL.

        name = callable_name(wrapped)

        transaction.set_transaction_name(name)

        # We need to add a reference to the request object in to the
        # transaction object as only able to stash the transaction
        # in a deferred. Need to use a weakref to avoid an object
        # cycle which may prevent cleanup of transaction.

        transaction._nr_current_request = weakref.ref(request)

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

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

        except:  # Catch all
            # If an error occurs assume that transaction should be
            # exited. Technically don't believe this should ever occur
            # unless our code here has an error.

            connection.stream._nr_close_callback = None

            _logger.exception('Unexpected exception raised by Tornado '
                    'HTTPConnection._on_headers().')

            transaction.__exit__(*sys.exc_info())
            request._nr_transaction = None

            raise

    module.HTTPConnection._on_headers = ObjectWrapper(
            module.HTTPConnection._on_headers, None, on_headers_wrapper)

    def on_request_body_wrapper(wrapped, instance, args, kwargs):
        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

        # If no transaction associated with the request we can call
        # through straight away. There should also be a current function
        # trace node.

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

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

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

        # Restore the transaction.

        transaction = request._nr_transaction

        transaction.save_transaction()

        # Exit the function trace node. This should correspond to the
        # reading of the request input.

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

        finally:
            request._nr_wait_function_trace = None

        try:
            # Now call the orginal wrapped function. It will in turn
            # call the application which will ensure the transaction
            # started here is popped off.

            return wrapped(*args, **kwargs)

        except:  # Catch all
            # If an error occurs assume that transaction should be
            # exited. Technically don't believe this should ever occur
            # unless our code here has an error.

            _logger.exception('Unexpected exception raised by Tornado '
                    'HTTPConnection._on_request_body().')

            transaction.__exit__(*sys.exc_info())
            request._nr_transaction = None

            raise

    module.HTTPConnection._on_request_body = ObjectWrapper(
            module.HTTPConnection._on_request_body, None,
            on_request_body_wrapper)

    def finish_request_wrapper(wrapped, instance, args, kwargs):
        assert instance is not None

        request = instance._request

        transaction = current_transaction()

        if transaction:
            request._nr_request_finished = True

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

                if (hasattr(request, '_nr_wait_function_trace') and
                        request._nr_wait_function_trace):
                    request._nr_wait_function_trace.__exit__(None, None, None)

            finally:
                request._nr_wait_function_trace = None

            return result

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

            transaction = request._nr_transaction

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

            transaction.save_transaction()

            request._nr_request_finished = True

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

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

                transaction.__exit__(None, None, None)

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

            finally:
                request._nr_wait_function_trace = None
                request._nr_transaction = None

            return result

    module.HTTPConnection._finish_request = ObjectWrapper(
            module.HTTPConnection._finish_request, None,
            finish_request_wrapper)

    def finish_wrapper(wrapped, instance, args, kwargs):
        assert instance is not None

        request = instance

        # Call finish() method straight away if request object it is
        # being called on is not even associated with a transaction.

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

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

        # Do we have a running transaction. When we do 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.

        running_transaction = current_transaction()

        if running_transaction:
            if transaction != running_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.

                try:
                    running_transaction.drop_transaction()

                    return finish_wrapper(wrapped, instance, args, kwargs)

                finally:
                    running_transaction.save_transaction()

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

                with FunctionTrace(transaction, name='Request/Finish',
                        group='Python/Tornado'):
                    return wrapped(*args, **kwargs)

        # No current running transaction. If we aren't in a wait state
        # we call finish() straight away.

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

        # Now handle the special case where finish() was called while in
        # the wait state. We need to restore the transaction for the
        # request and then call finish(). When it returns we need to
        # either end the transaction or go into a new wait state where
        # we wait on output to be sent.

        transaction.save_transaction()

        try:
            complete = True

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

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

            if not request.connection.stream.writing():
                transaction.__exit__(None, None, None)

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

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

                complete = False

            return result

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

        finally:
            if complete:
                request._nr_wait_function_trace = None
                request._nr_transaction = None

    module.HTTPRequest.finish = ObjectWrapper(
            module.HTTPRequest.finish, None, finish_wrapper)

    if hasattr(module.HTTPRequest, '_parse_mime_body'):
        wrap_function_trace(module.HTTPRequest, '_parse_mime_body')
Пример #20
0
def instrument_tornado_ioloop(module):

    wrap_function_trace(module, 'IOLoop.add_handler')
    wrap_function_trace(module, 'IOLoop.add_timeout')
    wrap_function_trace(module, 'IOLoop.add_callback')

    if hasattr(module.IOLoop, 'add_future'):
        wrap_function_trace(module, 'IOLoop.add_future')

    if hasattr(module, 'PollIOLoop'):
        wrap_function_trace(module, 'PollIOLoop.add_handler')
        wrap_function_trace(module, 'PollIOLoop.add_timeout')
        wrap_function_trace(module, 'PollIOLoop.add_callback')
        wrap_function_trace(module, 'PollIOLoop.add_callback_from_signal')
Пример #21
0
def instrument_cherrypy__cprequest(module):
    wrap_function_trace(module, 'Request.handle_error')
Пример #22
0
def instrument_flask_app(module):
    wrap_wsgi_application(module, "Flask.wsgi_app", framework=framework_details)

    wrap_function_wrapper(module, "Flask.add_url_rule", _nr_wrapper_Flask_add_url_rule_input_)

    if hasattr(module.Flask, "endpoint"):
        wrap_function_wrapper(module, "Flask.endpoint", _nr_wrapper_Flask_endpoint_)

    wrap_function_wrapper(module, "Flask.handle_http_exception", _nr_wrapper_Flask_handle_http_exception_)

    # Use the same wrapper for initial user exception processing and
    # fallback for unhandled exceptions.

    if hasattr(module.Flask, "handle_user_exception"):
        wrap_function_wrapper(module, "Flask.handle_user_exception", _nr_wrapper_Flask_handle_exception_)

    wrap_function_wrapper(module, "Flask.handle_exception", _nr_wrapper_Flask_handle_exception_)

    # The _register_error_handler() method was only introduced in
    # Flask version 0.7.0.
    if hasattr(module.Flask, "_register_error_handler"):
        wrap_function_wrapper(
            module,
            "Flask._register_error_handler",
            _nr_wrapper_Flask__register_error_handler_,
        )

    # The method changed name to register_error_handler() in
    # Flask version 2.0.0.
    elif hasattr(module.Flask, "register_error_handler"):
        wrap_function_wrapper(
            module,
            "Flask.register_error_handler",
            _nr_wrapper_Flask_register_error_handler_,
        )

    # Different before/after methods were added in different versions.
    # Check for the presence of everything before patching.

    if hasattr(module.Flask, "try_trigger_before_first_request_functions"):
        wrap_function_wrapper(
            module,
            "Flask.try_trigger_before_first_request_functions",
            _nr_wrapper_Flask_try_trigger_before_first_request_functions_,
        )
        wrap_function_wrapper(
            module,
            "Flask.before_first_request",
            _nr_wrapper_Flask_before_first_request_,
        )

    if hasattr(module.Flask, "preprocess_request"):
        wrap_function_trace(module, "Flask.preprocess_request")
        wrap_function_wrapper(module, "Flask.before_request", _nr_wrapper_Flask_before_request_)

    if hasattr(module.Flask, "process_response"):
        wrap_function_trace(module, "Flask.process_response")
        wrap_function_wrapper(module, "Flask.after_request", _nr_wrapper_Flask_after_request_)

    if hasattr(module.Flask, "do_teardown_request"):
        wrap_function_trace(module, "Flask.do_teardown_request")
        wrap_function_wrapper(module, "Flask.teardown_request", _nr_wrapper_Flask_teardown_request_)

    if hasattr(module.Flask, "do_teardown_appcontext"):
        wrap_function_trace(module, "Flask.do_teardown_appcontext")
        wrap_function_wrapper(module, "Flask.teardown_appcontext", _nr_wrapper_Flask_teardown_appcontext_)
def instrument_django_core_mail(module):
    wrap_function_trace(module, 'mail_admins')
    wrap_function_trace(module, 'mail_managers')
    wrap_function_trace(module, 'send_mail')
Пример #24
0
def instrument_django_core_mail_message(module):
    wrap_function_trace(module, 'EmailMessage.send')
Пример #25
0
def instrument_django_http_multipartparser(module):
    wrap_function_trace(module, 'MultiPartParser.parse')
def instrument_tornado_httputil(module):

    if hasattr(module, 'parse_body_arguments'):
        wrap_function_trace(module, 'parse_body_arguments')
    if hasattr(module, 'parse_multipart_form_data'):
        wrap_function_trace(module, 'parse_multipart_form_data')
def instrument_tornado_curl_httpclient(module):

    wrap_function_trace(module, 'CurlAsyncHTTPClient.fetch')
def instrument_tornado_httpserver(module):
    def on_headers_wrapper(wrapped, instance, args, kwargs):
        assert instance is not None

        connection = instance

        # Check to see if we are being called within the context of any
        # sort of transaction. If we are, then we don't bother doing
        # anything and just call the wrapped function. This should not
        # really ever occur but check anyway.

        transaction = current_transaction()

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

        # Execute the wrapped function as we are only going to do
        # something after it has been called. The function doesn't
        # return anything.

        wrapped(*args, **kwargs)

        # Check to see if the connection has already been closed or the
        # request finished. The connection can be closed where request
        # content length was too big.

        if connection.stream.closed():
            return

        if connection._request_finished:
            return

        # Check to see if have already associated a transaction with
        # the request, because if we have, even if not finished, then
        # do not need to do anything.

        request = connection._request

        if request is None:
            return

        if hasattr(request, '_nr_transaction'):
            return

        # Always use the default application specified in the agent
        # configuration.

        application = application_instance()

        # We need to fake up a WSGI like environ dictionary with the
        # key bits of information we need.

        environ = request_environment(application, request)

        # Now start recording the actual web transaction. Bail out
        # though if turns out that recording transactions is not
        # enabled.

        transaction = WebTransaction(application, environ)

        if not transaction.enabled:
            return

        transaction.__enter__()

        request._nr_transaction = transaction

        request._nr_wait_function_trace = None
        request._nr_request_finished = False

        # Add a callback variable to the connection object so we can
        # be notified when the connection is closed before all content
        # has been read.

        def _close():
            transaction.save_transaction()

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

            finally:
                request._nr_wait_function_trace = None

            transaction.__exit__(None, None, None)
            request._nr_transaction = None

        connection.stream._nr_close_callback = _close

        # Name transaction initially after the wrapped function so
        # that if connection dropped before request content read,
        # then don't get metric grouping issues with it being named
        # after the URL.

        name = callable_name(wrapped)

        transaction.set_transaction_name(name)

        # We need to add a reference to the request object in to the
        # transaction object as only able to stash the transaction
        # in a deferred. Need to use a weakref to avoid an object
        # cycle which may prevent cleanup of transaction.

        transaction._nr_current_request = weakref.ref(request)

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

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

        except:  # Catch all
            # If an error occurs assume that transaction should be
            # exited. Technically don't believe this should ever occur
            # unless our code here has an error.

            connection.stream._nr_close_callback = None

            _logger.exception('Unexpected exception raised by Tornado '
                              'HTTPConnection._on_headers().')

            transaction.__exit__(*sys.exc_info())
            request._nr_transaction = None

            raise

    module.HTTPConnection._on_headers = ObjectWrapper(
        module.HTTPConnection._on_headers, None, on_headers_wrapper)

    def on_request_body_wrapper(wrapped, instance, args, kwargs):
        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

        # If no transaction associated with the request we can call
        # through straight away. There should also be a current function
        # trace node.

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

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

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

        # Restore the transaction.

        transaction = request._nr_transaction

        transaction.save_transaction()

        # Exit the function trace node. This should correspond to the
        # reading of the request input.

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

        finally:
            request._nr_wait_function_trace = None

        try:
            # Now call the orginal wrapped function. It will in turn
            # call the application which will ensure the transaction
            # started here is popped off.

            return wrapped(*args, **kwargs)

        except:  # Catch all
            # If an error occurs assume that transaction should be
            # exited. Technically don't believe this should ever occur
            # unless our code here has an error.

            _logger.exception('Unexpected exception raised by Tornado '
                              'HTTPConnection._on_request_body().')

            transaction.__exit__(*sys.exc_info())
            request._nr_transaction = None

            raise

    module.HTTPConnection._on_request_body = ObjectWrapper(
        module.HTTPConnection._on_request_body, None, on_request_body_wrapper)

    def finish_request_wrapper(wrapped, instance, args, kwargs):
        assert instance is not None

        request = instance._request

        transaction = current_transaction()

        if transaction:
            request._nr_request_finished = True

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

                if (hasattr(request, '_nr_wait_function_trace')
                        and request._nr_wait_function_trace):
                    request._nr_wait_function_trace.__exit__(None, None, None)

            finally:
                request._nr_wait_function_trace = None

            return result

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

            transaction = request._nr_transaction

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

            transaction.save_transaction()

            request._nr_request_finished = True

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

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

                transaction.__exit__(None, None, None)

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

            finally:
                request._nr_wait_function_trace = None
                request._nr_transaction = None

            return result

    module.HTTPConnection._finish_request = ObjectWrapper(
        module.HTTPConnection._finish_request, None, finish_request_wrapper)

    def finish_wrapper(wrapped, instance, args, kwargs):
        assert instance is not None

        request = instance

        # Call finish() method straight away if request object it is
        # being called on is not even associated with a transaction.

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

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

        # Do we have a running transaction. When we do 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.

        running_transaction = current_transaction()

        if running_transaction:
            if transaction != running_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.

                try:
                    running_transaction.drop_transaction()

                    return finish_wrapper(wrapped, instance, args, kwargs)

                finally:
                    running_transaction.save_transaction()

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

                with FunctionTrace(transaction,
                                   name='Request/Finish',
                                   group='Python/Tornado'):
                    return wrapped(*args, **kwargs)

        # No current running transaction. If we aren't in a wait state
        # we call finish() straight away.

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

        # Now handle the special case where finish() was called while in
        # the wait state. We need to restore the transaction for the
        # request and then call finish(). When it returns we need to
        # either end the transaction or go into a new wait state where
        # we wait on output to be sent.

        transaction.save_transaction()

        try:
            complete = True

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

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

            if not request.connection.stream.writing():
                transaction.__exit__(None, None, None)

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

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

                complete = False

            return result

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

        finally:
            if complete:
                request._nr_wait_function_trace = None
                request._nr_transaction = None

    module.HTTPRequest.finish = ObjectWrapper(module.HTTPRequest.finish, None,
                                              finish_wrapper)

    if hasattr(module.HTTPRequest, '_parse_mime_body'):
        wrap_function_trace(module.HTTPRequest, '_parse_mime_body')
Пример #29
0
def instrument_tornado_httputil(module):

    if hasattr(module, 'parse_body_arguments'):
        wrap_function_trace(module, 'parse_body_arguments')
    if hasattr(module, 'parse_multipart_form_data'):
        wrap_function_trace(module, 'parse_multipart_form_data')
Пример #30
0
def instrument_django_core_mail(module):
    wrap_function_trace(module, 'mail_admins')
    wrap_function_trace(module, 'mail_managers')
    wrap_function_trace(module, 'send_mail')
Пример #31
0
def instrument_tornado_curl_httpclient(module):

    wrap_function_trace(module, 'CurlAsyncHTTPClient.fetch')
def instrument_django_http_multipartparser(module):
    wrap_function_trace(module, 'MultiPartParser.parse')
Пример #33
0
def instrument_tornado_simple_httpclient(module):

    wrap_function_trace(module, 'SimpleAsyncHTTPClient.fetch')
def instrument_django_core_mail_message(module):
    wrap_function_trace(module, 'EmailMessage.send')
def instrument_tornado_ioloop(module):

    wrap_function_trace(module, "IOLoop.add_handler")
    wrap_function_trace(module, "IOLoop.add_timeout")
    wrap_function_trace(module, "IOLoop.add_callback")

    if hasattr(module.IOLoop, "add_future"):
        wrap_function_trace(module, "IOLoop.add_future")

    if hasattr(module, "PollIOLoop"):
        wrap_function_trace(module, "PollIOLoop.add_handler")
        wrap_function_trace(module, "PollIOLoop.add_timeout")
        wrap_function_trace(module, "PollIOLoop.add_callback")
        wrap_function_trace(module, "PollIOLoop.add_callback_from_signal")