def instrument(tracer=None): flask = utils.get_module('flask') if utils.is_instrumented(flask): return flask_opentracing = utils.get_module('flask_opentracing') def flask_tracer(__init__, app, args, kwargs): """ A function wrapper of flask.Flask.__init__ to create a corresponding flask_opentracing.FlaskTracer upon app instantiation. """ __init__(*args, **kwargs) _tracer = tracer or config.tracer or opentracing.tracer app.config['FLASK_TRACER'] = flask_opentracing.FlaskTracer( tracer=_tracer, trace_all_requests=config.trace_all, app=app, traced_attributes=config.traced_attributes) wrap_function_wrapper('flask', 'Flask.__init__', flask_tracer) utils.mark_instrumented(flask)
def instrument(tracer=None): """ Requests auto-instrumentation works by hooking a __new__ proxy for a SessionTracing instance upon requests.sessions.Session initialization to trigger proper inheritance. SessionTracing.__init__ is also wrapped for correct argument injection. """ requests = utils.get_module('requests') if utils.is_instrumented(requests): return def session_tracing_init(__init__, instance, _, __): _tracer = tracer or config.tracer or opentracing.tracer __init__(_tracer, propagate=config.propagate, span_tags=config.span_tags or {}) from requests_opentracing import SessionTracing _session_new[0] = requests.Session.__new__ _session_tracing_new[0] = SessionTracing.__new__ SessionTracing.__new__ = session_tracing_new.__get__(SessionTracing) requests.Session.__new__ = session_new.__get__(requests.Session) wrap_function_wrapper('requests_opentracing.tracing', 'SessionTracing.__init__', session_tracing_init) utils.mark_instrumented(requests)
def instrument(tracer=None): django = utils.get_module('django') if utils.is_instrumented(django): return settings = utils.get_module('django.conf').settings # Tracer settings (need to be before initialization) settings.OPENTRACING_TRACE_ALL = config.trace_all settings.OPENTRACING_TRACED_ATTRIBUTES = config.traced_attributes settings.OPENTRACING_SET_GLOBAL_TRACER = config.set_global_tracer # DjangoTracing will obtain global tracer for us _tracer = tracer or config.tracer if _tracer is not None: django_opentracing = utils.get_module('django_opentracing') settings.OPENTRACING_TRACING = django_opentracing.DjangoTracer(tracer) if config.tracer_callable: settings.OPENTRACING_TRACER_CALLABLE = config.tracer_callable settings.OPENTRACING_TRACER_PARAMETERS = config.tracer_parameters or {} middleware_classes, setting = get_middleware_and_setting_name() setattr(settings, setting, [config.middleware_class] + list(middleware_classes)) utils.mark_instrumented(django)
def instrument(tracer=None): """ Requests auto-instrumentation works by hooking a __new__ proxy for a CeleryTracing instance upon celery.Celery initialization to trigger proper inheritance. CeleryTracing.__init__ is also wrapped for correct argument injection. """ celery = utils.get_module('celery') if utils.is_instrumented(celery): return import celery.app def celery_tracing_init(__init__, instance, args, kwargs): _tracer = tracer or config.tracer or opentracing.tracer __init__(*args, tracer=_tracer, propagate=config.propagate, span_tags=config.span_tags or {}, **kwargs) from celery_opentracing import CeleryTracing _celery_new[0] = celery.Celery.__new__ _celery_tracing_new[0] = CeleryTracing.__new__ CeleryTracing.__new__ = celery_tracing_new.__get__(CeleryTracing) celery.app.base.Celery.__new__ = celery_new.__get__(celery.Celery) wrap_function_wrapper('celery_opentracing.tracing', 'CeleryTracing.__init__', celery_tracing_init) utils.mark_instrumented(celery)
def instrument(tracer=None): tornado = utils.get_module('tornado') if utils.is_instrumented(tornado): return tornado_opentracing = utils.get_module('tornado_opentracing') def _tracer_config(wrapped_tracer_config, _, wrapt_args, __): """ A function wrapper for tornado_opentracing's monkey patcher of tornado.web.Application.__init__() used to inject tracer configuration as settings arguments. As a wrapt function wrapper of a function_wrapper, _tracer_config's meaningful arguments are oddly nested. """ __init__ = wrapt_args[0] app = wrapt_args[1] args = wrapt_args[2] kwargs = wrapt_args[3] _tracer = tracer or config.tracer or opentracing.tracer kwargs['opentracing_tracing'] = tornado_opentracing.TornadoTracing(_tracer) kwargs['opentracing_trace_all'] = config.trace_all kwargs['opentracing_trace_client'] = config.trace_client kwargs['opentracing_traced_attributes'] = config.traced_attributes kwargs['opentracing_start_span_cb'] = config.start_span_cb wrapped_tracer_config(__init__, app, args, kwargs) wrap_function_wrapper('tornado_opentracing.application', 'tracer_config', _tracer_config) tornado_opentracing.init_tracing() utils.mark_instrumented(tornado)
def instrument(tracer=None): pymongo = utils.get_module('pymongo') if utils.is_instrumented(pymongo): return pymongo_opentracing = utils.get_module('pymongo_opentracing') def pymongo_tracer(__init__, app, args, kwargs): """ A function wrapper of pymongo.MongoClient.__init__ to register a corresponding pymongo_opentracing.CommandTracing upon client instantiation. """ _tracer = tracer or config.tracer or opentracing.tracer command_tracing = pymongo_opentracing.CommandTracing( tracer=_tracer, span_tags=config.span_tags or {}, ) event_listeners = list(kwargs.pop('event_listeners', [])) event_listeners.insert(0, command_tracing) kwargs['event_listeners'] = event_listeners __init__(*args, **kwargs) wrap_function_wrapper('pymongo', 'MongoClient.__init__', pymongo_tracer) utils.mark_instrumented(pymongo)
def test_mark_instrumented_and_uninstrumented(): class MockModule(object): pass module = MockModule() utils.mark_instrumented(module) assert getattr(module, constants.instrumented_attr) is True assert utils.is_instrumented(module) is True utils.mark_uninstrumented(module) assert not hasattr(module, constants.instrumented_attr) assert utils.is_instrumented(module) is False
def instrument(tracer=None): aioredis = utils.get_module('aioredis') if utils.is_instrumented(aioredis): return tracing.init_tracing(tracer=tracer or config.tracer or opentracing.tracer) def traced_client(__init__, client, args, kwargs): __init__(*args, **kwargs) tracing.trace_client(client) wrap_function_wrapper('aioredis', 'Redis.__init__', traced_client) utils.mark_instrumented(aioredis)
def instrument(tracer=None): redis = utils.get_module('redis') if utils.is_instrumented(redis): return redis_opentracing = utils.get_module('redis_opentracing') redis_opentracing.init_tracing(tracer=tracer or config.tracer or opentracing.tracer, trace_all_classes=False) def traced_client(__init__, client, args, kwargs): __init__(*args, **kwargs) redis_opentracing.trace_client(client) wrap_function_wrapper('redis.client', 'StrictRedis.__init__', traced_client) utils.mark_instrumented(redis)
def instrument(tracer=None): falcon = utils.get_module("falcon") if utils.is_instrumented(falcon): return _tracer = tracer or config.tracer or opentracing.tracer def traced_init(wrapped, instance, args, kwargs): mw = kwargs.pop("middleware", []) mw.insert(0, TraceMiddleware(_tracer, config.traced_attributes)) kwargs["middleware"] = mw wrapped(*args, **kwargs) wrap_function_wrapper("falcon", "API.__init__", traced_init) utils.mark_instrumented(falcon)
def instrument(tracer=None): pymysql = utils.get_module('pymysql') if utils.is_instrumented(pymysql): return dbapi_opentracing = utils.get_module('dbapi_opentracing') def pymysql_tracer(connect, _, args, kwargs): """ A function wrapper of pymysql.connect() to create a corresponding dbapi_opentracing.ConnectionTracing upon database connection. """ connection = connect(*args, **kwargs) _tracer = tracer or config.tracer or opentracing.tracer traced_commands = set(config.traced_commands) traced_commands_kwargs = dict(trace_execute=False, trace_executemany=False, trace_callproc=False, trace_commit=False, trace_rollback=False) for command in traced_commands: flag = 'trace_{}'.format(command.lower()) if flag not in traced_commands_kwargs: log.warn( 'Unable to trace PyMySQL command "{}". Ignoring.'.format( command)) continue traced_commands_kwargs[flag] = True span_tags = {tags.DATABASE_TYPE: 'MySQL'} if connection.db is not None: span_tags[tags.DATABASE_INSTANCE] = ensure_str(connection.db) if config.span_tags is not None: span_tags.update(config.span_tags) return dbapi_opentracing.ConnectionTracing(connection, _tracer, span_tags=span_tags, **traced_commands_kwargs) wrap_function_wrapper('pymysql', 'connect', pymysql_tracer) utils.mark_instrumented(pymysql)
def instrument(tracer=None): bottle = utils.get_module('bottle') if utils.is_instrumented(bottle): return def bottle_tracer(run, _, args, kwargs): """ A function wrapper of bottle.run to create a corresponding BottleTracer upon app instantiation. """ app = kwargs.get('app', default_app()) _tracer = tracer or config.tracer or opentracing.tracer BottleTracing(tracer=_tracer, trace_all_requests=config.trace_all, app=app, traced_attributes=config.traced_attributes) run(**kwargs) wrap_function_wrapper('bottle', 'run', bottle_tracer) utils.mark_instrumented(bottle)
def instrument(tracer=None): """ Unlike all other instrumentations, this instrumentation does not patch the logging lib to automatically generate spans. Instead it patches the lib to automatically inject trace context into logs. """ logging = utils.get_module('logging') if utils.is_instrumented(logging): return wrap_function_wrapper(logging, 'Logger.makeRecord', makeRecordPatched) if config.injection_enabled: level = logging.INFO if utils.is_truthy(os.environ.get('SIGNALFX_TRACING_DEBUG', False)): level = logging.DEBUG logging.basicConfig(level=level, format=config.logging_format) utils.mark_instrumented(logging)
def instrument(tracer=None): """ Elasticsearch auto-instrumentation works by hooking a __new__ proxy for a TracingTransport instance upon elasticsearch.transports.Transport initialization to trigger proper inheritance. """ elasticsearch = utils.get_module('elasticsearch') if utils.is_instrumented(elasticsearch): return from elasticsearch_opentracing import init_tracing, TracingTransport _tracer = tracer or config.tracer or opentracing.tracer init_tracing(_tracer, trace_all_requests=True, prefix=config.prefix) _transport_new[0] = elasticsearch.transport.Transport.__new__ _tracing_transport_new[0] = TracingTransport.__new__ TracingTransport.__new__ = tracing_transport_new.__get__(TracingTransport) elasticsearch.transport.Transport.__new__ = transport_new.__get__( elasticsearch.transport.Transport) utils.mark_instrumented(elasticsearch)
def instrument(tracer=None): psycopg2 = utils.get_module('psycopg2') if psycopg2 is None or utils.is_instrumented(psycopg2): return dbapi_opentracing = utils.get_module('dbapi_opentracing') if dbapi_opentracing is None: return def psycopg2_tracer(connect, _, args, kwargs): """ A function wrapper of psycopg2.connect() to create a corresponding dbapi_opentracing.ConnectionTracing upon database connection. """ _tracer = tracer or config.tracer or opentracing.tracer traced_commands = set(config.traced_commands) traced_commands_kwargs = dict(trace_execute=False, trace_executemany=False, trace_callproc=False, trace_commit=False, trace_rollback=False) for command in traced_commands: flag = 'trace_{}'.format(command.lower()) if flag not in traced_commands_kwargs: log.warn( 'Unable to trace Psycopg command "{}". Ignoring.'.format( command)) continue traced_commands_kwargs[flag] = True span_tags = {tags.DATABASE_TYPE: 'PostgreSQL'} if config.span_tags is not None: span_tags.update(config.span_tags) if 'connection_factory' in kwargs: connection_factory = kwargs['connection_factory'] if not inspect.isclass(connection_factory): log.error( 'connection_factory value %s is not a class, so it cannot be subclassed along with ' 'PsycopgConnectionTracing. No auto-instrumentation possible.', connection_factory) return connect(*args, **kwargs) traced_commands_kwargs['connection_factory'] = kwargs.pop( 'connection_factory') traced_commands_kwargs['tracer'] = _tracer traced_commands_kwargs['span_tags'] = span_tags def init_psycopg_connection_tracing(*a): return dbapi_opentracing.PsycopgConnectionTracing( *a, **traced_commands_kwargs) connection = connect( *args, connection_factory=init_psycopg_connection_tracing, **kwargs) if tags.DATABASE_INSTANCE not in span_tags: db_name = connection.get_dsn_parameters().get('dbname') if db_name: span_tags[tags.DATABASE_INSTANCE] = db_name return connection wrap_function_wrapper('psycopg2', 'connect', psycopg2_tracer) utils.mark_instrumented(psycopg2)
def _instrument(tracer=None): utils.mark_instrumented(module_stub)