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_pymongo_connection(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, 'Connection.__init__', name='%s:Connection.__init__' % module.__name__, terminal=True, rollup=rollup)
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)
def instrument_dyndns53(module): wrap_function_trace(module, 'initialise_database') wrap_function_trace(module, 'download_database') wrap_function_trace(module, 'upload_database') wrap_function_trace(module, 'register_ip') wrap_function_trace(module, 'BasicAuthDatabase.check_credentials') wrap_background_task(module, 'upload_database_command') wrap_background_task(module, 'download_database_command') wrap_function_wrapper(module, 'register_ip', wrapper_register_ip)
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')
def instrument_dyndns53(module): wrap_function_trace(module, 'initialise_database') wrap_function_trace(module, 'download_database') wrap_function_trace(module, 'upload_database') wrap_function_trace(module, 'register_ip') wrap_function_trace(module, 'BasicAuthDatabase.check_credentials') wrap_function_wrapper(module, 'register_ip', wrapper_register_ip) for name, callback in list(module._commands.items()): module._commands[name] = BackgroundTaskWrapper(callback)
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_)
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')
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') # Django 1.8 no longer has module.libraries. As automatic way is not # preferred we can just skip this now. if not hasattr(module, 'libraries'): return # 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_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')
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')
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")
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') 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)
def instrument_cherrypy__cprequest(module): wrap_function_trace(module, 'Request.handle_error')
def instrument_cherrypy__cpreqbody(module): wrap_function_trace(module, 'process_multipart') wrap_function_trace(module, 'process_multipart_form_data')
def instrument_weberror_errormiddleware(module): wrap_function_trace(module, 'handle_exception')
def instrument_flask_templating(module): wrap_function_trace(module, 'render_template') wrap_function_trace(module, 'render_template_string')
def patch_context(self): module = importlib.import_module('fabric.connection') wrap_function_trace(module, 'Connection.run') wrap_function_trace(module, 'Connection.sudo')
def instrument_tornado_curl_httpclient(module): wrap_function_trace(module, 'CurlAsyncHTTPClient.fetch')
def patch_zag_tasks_in_projects(self, project_packages): task_module = importlib.import_module('zag.task') to_patch = [ cls for package in project_packages for child in py.get_child_modules(py.get_module_by_name(package)) for cls in py.get_all_inherited_classes(child, task_module.Task) ] for cls in to_patch: module = py.get_module_by_name(cls.__module__) wrap_function_trace(module, '{0}.pre_execute'.format(cls.__name__)) wrap_function_trace(module, '{0}.execute'.format(cls.__name__)) wrap_function_trace(module, '{0}.post_execute'.format(cls.__name__)) wrap_function_trace(module, '{0}.pre_revert'.format(cls.__name__)) wrap_function_trace(module, '{0}.revert'.format(cls.__name__)) wrap_function_trace(module, '{0}.post_revert'.format(cls.__name__))
def instrument_django_core_mail_message(module): wrap_function_trace(module, 'EmailMessage.send')
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_django_core_mail(module): wrap_function_trace(module, 'mail_admins') wrap_function_trace(module, 'mail_managers') wrap_function_trace(module, 'send_mail')
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_)
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') wrap_function_wrapper( module, 'GearmanClient.poll_connections_until_stopped', wrapper_GearmanClient_poll_connections_until_stopped)
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_tornado_simple_httpclient(module): wrap_function_trace(module, 'SimpleAsyncHTTPClient.fetch')
def instrument_django_http_multipartparser(module): wrap_function_trace(module, 'MultiPartParser.parse')