def patch(): """ Tracing function that patches the Tornado web application so that it will be traced using the given ``tracer``. """ # patch only once if getattr(tornado, '__opentelemetry_patch', False): return setattr(tornado, '__opentelemetry_patch', True) # patch Application to initialize properly our settings and tracer _w('tornado.web', 'Application.__init__', application.tracer_config) # patch RequestHandler to trace all Tornado handlers _w('tornado.web', 'RequestHandler._execute', handlers.execute) _w('tornado.web', 'RequestHandler.on_finish', handlers.on_finish) _w('tornado.web', 'RequestHandler.log_exception', handlers.log_exception) # patch Template system _w('tornado.template', 'Template.generate', template.generate) # patch Python Futures if available when an Executor pool is used compat.wrap_futures() # configure the global tracer oteltrace.tracer.configure( context_provider=context_provider, wrap_executor=decorators.wrap_executor, )
def patch(): """Enables Context Propagation between threads""" if getattr(futures, '__opentelemetry_patch', False): return setattr(futures, '__opentelemetry_patch', True) _w('concurrent.futures', 'ThreadPoolExecutor.submit', _wrap_submit)
def _patch(elasticsearch): if getattr(elasticsearch, '_opentelemetry_patch', False): return setattr(elasticsearch, '_opentelemetry_patch', True) _w(elasticsearch.transport, 'Transport.perform_request', _get_perform_request(elasticsearch)) Pin(service=metadata.SERVICE, app=metadata.APP, app_type=AppTypes.db).onto(elasticsearch.transport.Transport)
def _patch_server(): if getattr(constants.GRPC_PIN_MODULE_SERVER, '__opentelemetry_patch', False): return setattr(constants.GRPC_PIN_MODULE_SERVER, '__opentelemetry_patch', True) Pin(service=config.grpc_server.service_name).onto( constants.GRPC_PIN_MODULE_SERVER) _w('grpc', 'server', _server_constructor_interceptor)
def patch(): if getattr(consul, '__opentelemetry_patch', False): return setattr(consul, '__opentelemetry_patch', True) pin = Pin(service=consulx.SERVICE, app=consulx.APP, app_type=consulx.APP_TYPE) pin.onto(consul.Consul.KV) for f_name in _KV_FUNCS: _w('consul', 'Consul.KV.%s' % f_name, wrap_function(f_name))
def patch(): """Patches current loop `create_task()` method to enable spawned tasks to parent to the base task context. """ if getattr(asyncio, '_opentelemetry_patch', False): return setattr(asyncio, '_opentelemetry_patch', True) loop = asyncio.get_event_loop() if CONTEXTVARS_IS_AVAILABLE: _w(loop, 'create_task', wrapped_create_task_contextvars) else: _w(loop, 'create_task', wrapped_create_task)
def trace_rendering(): """Patch all Pylons renderers. It supports multiple versions of Pylons and multiple renderers. """ # patch only once if getattr(pylons.templating, '__opentelemetry_patch', False): return setattr(pylons.templating, '__opentelemetry_patch', True) if legacy_pylons: # Pylons <= 0.9.7 _w('pylons.templating', 'render', _traced_renderer) else: # Pylons > 0.9.7 _w('pylons.templating', 'render_mako', _traced_renderer) _w('pylons.templating', 'render_mako_def', _traced_renderer) _w('pylons.templating', 'render_genshi', _traced_renderer) _w('pylons.templating', 'render_jinja2', _traced_renderer)
def patch(): """Patch the instrumented methods """ if getattr(molten, '_opentelemetry_patch', False): return setattr(molten, '_opentelemetry_patch', True) pin = Pin( service=config.molten['service_name'], app=config.molten['app'], app_type=config.molten['app_type'], ) # add pin to module since many classes use __slots__ pin.onto(molten) _w(molten.BaseApp, '__init__', patch_app_init) _w(molten.App, '__call__', patch_app_call)
def patch(): if getattr(jinja2, '__opentelemetry_patch', False): # already patched return setattr(jinja2, '__opentelemetry_patch', True) Pin( service=config.jinja2['service_name'], _config=config.jinja2, ).onto(jinja2.environment.Environment) _w(jinja2, 'environment.Template.render', _wrap_render) _w(jinja2, 'environment.Template.generate', _wrap_render) _w(jinja2, 'environment.Environment.compile', _wrap_compile) _w(jinja2, 'environment.Environment._load_template', _wrap_load_template)
def patch(): """Activate http calls tracing""" if getattr(requests, '__opentelemetry_patch', False): return setattr(requests, '__opentelemetry_patch', True) _w('requests', 'Session.send', _wrap_send) Pin( service=config.requests['service_name'], app='requests', app_type=AppTypes.web, _config=config.requests, ).onto(requests.Session) # [Backward compatibility]: `session.distributed_tracing` should point and # update the `Pin` configuration instead. This block adds a property so that # old implementations work as expected fn = property(_distributed_tracing) fn = fn.setter(_distributed_tracing_setter) requests.Session.distributed_tracing = fn
def patch(): if algoliasearch_version == (0, 0): return if getattr(algoliasearch, OTEL_PATCH_ATTR, False): return setattr(algoliasearch, '_opentelemetry_patch', True) pin = Pin( service=config.algoliasearch.service_name, app=APP_NAME, app_type=AppTypes.db ) if algoliasearch_version < (2, 0) and algoliasearch_version >= (1, 0): _w(algoliasearch.index, 'Index.search', _patched_search) pin.onto(algoliasearch.index.Index) elif algoliasearch_version >= (2, 0) and algoliasearch_version < (3, 0): from algoliasearch import search_index _w(algoliasearch, 'search_index.SearchIndex.search', _patched_search) pin.onto(search_index.SearchIndex) else: return
def _patch_client(): if getattr(constants.GRPC_PIN_MODULE_CLIENT, '__opentelemetry_patch', False): return setattr(constants.GRPC_PIN_MODULE_CLIENT, '__opentelemetry_patch', True) Pin(service=config.grpc.service_name).onto( constants.GRPC_PIN_MODULE_CLIENT) _w('grpc', 'insecure_channel', _client_channel_interceptor) _w('grpc', 'secure_channel', _client_channel_interceptor) _w('grpc', 'intercept_channel', intercept_channel)
def patch(): # patch only once if getattr(MySQLdb, '__opentelemetry_patch', False): return setattr(MySQLdb, '__opentelemetry_patch', True) # `Connection` and `connect` are aliases for # `Connect`; patch them too _w('MySQLdb', 'Connect', _connect) if hasattr(MySQLdb, 'Connection'): _w('MySQLdb', 'Connection', _connect) if hasattr(MySQLdb, 'connect'): _w('MySQLdb', 'connect', _connect)
# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import requests from oteltrace.vendor.wrapt import wrap_function_wrapper as _w from .connection import _wrap_send class TracedSession(requests.Session): """TracedSession is a requests' Session that is already traced. You can use it if you want a finer grained control for your HTTP clients. """ pass # always patch our `TracedSession` when imported _w(TracedSession, 'send', _wrap_send)
def patch(): """ Patch `flask` module for tracing """ # Check to see if we have patched Flask yet or not if getattr(flask, '_opentelemetry_patch', False): return setattr(flask, '_opentelemetry_patch', True) # Attach service pin to `flask.app.Flask` Pin( service=config.flask['service_name'], app=config.flask['app'], app_type=config.flask['app_type'], ).onto(flask.Flask) # flask.app.Flask methods that have custom tracing (add metadata, wrap functions, etc) _w('flask', 'Flask.wsgi_app', traced_wsgi_app) _w('flask', 'Flask.dispatch_request', request_tracer('dispatch_request')) _w('flask', 'Flask.preprocess_request', request_tracer('preprocess_request')) _w('flask', 'Flask.add_url_rule', traced_add_url_rule) _w('flask', 'Flask.endpoint', traced_endpoint) _w('flask', 'Flask._register_error_handler', traced_register_error_handler) # flask.blueprints.Blueprint methods that have custom tracing (add metadata, wrap functions, etc) _w('flask', 'Blueprint.register', traced_blueprint_register) _w('flask', 'Blueprint.add_url_rule', traced_blueprint_add_url_rule) # flask.app.Flask traced hook decorators flask_hooks = [ 'before_request', 'before_first_request', 'after_request', 'teardown_request', 'teardown_appcontext', ] for hook in flask_hooks: _w('flask', 'Flask.{}'.format(hook), traced_flask_hook) _w('flask', 'after_this_request', traced_flask_hook) # flask.app.Flask traced methods flask_app_traces = [ 'process_response', 'handle_exception', 'handle_http_exception', 'handle_user_exception', 'try_trigger_before_first_request_functions', 'do_teardown_request', 'do_teardown_appcontext', 'send_static_file', ] for name in flask_app_traces: _w('flask', 'Flask.{}'.format(name), simple_tracer('flask.{}'.format(name))) # flask static file helpers _w('flask', 'send_file', simple_tracer('flask.send_file')) # flask.json.jsonify _w('flask', 'jsonify', traced_jsonify) # flask.templating traced functions _w('flask.templating', '_render', traced_render) _w('flask', 'render_template', traced_render_template) _w('flask', 'render_template_string', traced_render_template_string) # flask.blueprints.Blueprint traced hook decorators bp_hooks = [ 'after_app_request', 'after_request', 'before_app_first_request', 'before_app_request', 'before_request', 'teardown_request', 'teardown_app_request', ] for hook in bp_hooks: _w('flask', 'Blueprint.{}'.format(hook), traced_flask_hook) # flask.signals signals if config.flask['trace_signals']: signals = [ 'template_rendered', 'request_started', 'request_finished', 'request_tearing_down', 'got_request_exception', 'appcontext_tearing_down', ] # These were added in 0.11.0 if flask_version >= (0, 11): signals.append('before_render_template') # These were added in 0.10.0 if flask_version >= (0, 10): signals.append('appcontext_pushed') signals.append('appcontext_popped') signals.append('message_flashed') for signal in signals: module = 'flask' # v0.9 missed importing `appcontext_tearing_down` in `flask/__init__.py` # https://github.com/pallets/flask/blob/0.9/flask/__init__.py#L35-L37 # https://github.com/pallets/flask/blob/0.9/flask/signals.py#L52 # DEV: Version 0.9 doesn't have a patch version if flask_version <= (0, 9) and signal == 'appcontext_tearing_down': module = 'flask.signals' # DEV: Patch `receivers_for` instead of `connect` to ensure we don't mess with `disconnect` _w(module, '{}.receivers_for'.format(signal), traced_signal_receivers_for(signal))