Example #1
0
    def test_env_var_disables_instrument(self, env_var, are_uninstrumented):
        os.environ['SIGNALFX_TRACING_ENABLED'] = env_var
        modules = [utils.get_module(l) for l in expected_traceable_libraries]
        assert self.all_are_uninstrumented(modules)

        for m in expected_traceable_libraries:
            instrument(**{m: True})

        assert self.all_are_uninstrumented(modules) is are_uninstrumented
Example #2
0
def uninstrument():
    """Will only prevent new clients from registering tracers."""
    redis = utils.get_module('redis')
    if not utils.is_instrumented(redis):
        return

    from redis.client import StrictRedis
    utils.revert_wrapper(StrictRedis, '__init__')
    utils.mark_uninstrumented(redis)
Example #3
0
 def test_instrument_with_true_and_env_var_false_doesnt_instrument_specified_libraries(
         self, module_name):
     env_var = 'SIGNALFX_{0}_ENABLED'.format(module_name.upper())
     os.environ[env_var] = 'False'
     try:
         instrument(**{module_name: True})
         mod = utils.get_module(module_name)
         assert not hasattr(mod, instrumented_attr)
     finally:
         os.environ.pop(env_var)
Example #4
0
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 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)
Example #5
0
    def test_env_var_disables_prevents_auto_instrument(self, env_var,
                                                       are_uninstrumented):
        os.environ['SIGNALFX_TRACING_ENABLED'] = env_var
        modules = [
            utils.get_module(l) for l in expected_auto_instrumentable_libraries
        ]
        assert self.all_are_uninstrumented(modules)

        auto_instrument()

        assert self.all_are_uninstrumented(modules) is are_uninstrumented
Example #6
0
def test_get_module_imports_unimported_modules():
    restore_logging = False
    if 'logging' in sys.modules:
        restore_logging = True
        del sys.modules['logging']
    try:
        logging = utils.get_module('logging')
        assert logging == sys.modules['logging']
    finally:
        if restore_logging:
            import logging
def uninstrument():
    """
    Will only prevent new Connections from registering tracers.
    It's not reasonably feasible to unwrap existing ConnectionTracing instances
    """
    psycopg2 = utils.get_module('psycopg2')
    if not utils.is_instrumented(psycopg2):
        return

    utils.revert_wrapper(psycopg2, 'connect')
    utils.mark_uninstrumented(psycopg2)
Example #8
0
def uninstrument():
    """
    Will only prevent new applications from registering tracers.
    It's not reasonably feasible to remove existing before/after_request
    trace methods of existing apps.
    """
    bottle = utils.get_module('bottle')
    if not utils.is_instrumented(bottle):
        return

    utils.revert_wrapper(bottle, 'run')
    utils.mark_uninstrumented(bottle)
def uninstrument():
    """
    Will only prevent new applications from registering tracers.
    It's not reasonably feasible to remove existing before/after_request
    trace methods of existing apps.
    """
    flask = utils.get_module('flask')
    if not utils.is_instrumented(flask):
        return

    utils.revert_wrapper(flask.Flask, '__init__')
    utils.mark_uninstrumented(flask)
Example #10
0
def uninstrument():
    """
    Will only prevent new clients from registering tracers.
    It's not reasonably feasible to remove existing before/after_request
    trace methods of existing clients.
    """
    pymongo = utils.get_module('pymongo')
    if not utils.is_instrumented(pymongo):
        return

    utils.revert_wrapper(pymongo.MongoClient, '__init__')
    utils.mark_uninstrumented(pymongo)
Example #11
0
    def test_auto_instrument_instruments_all_available_libraries(self):
        modules = [(utils.get_module(l), l)
                   for l in expected_traceable_libraries]
        assert self.all_are_uninstrumented(modules)

        auto_instrument()

        for module, library in modules:
            if library in expected_auto_instrumentable_libraries:
                assert getattr(module, instrumented_attr) is True
            else:
                assert not hasattr(module, instrumented_attr)
def uninstrument():
    django = utils.get_module('django')
    if not utils.is_instrumented(django):
        return

    settings = utils.get_module('django.conf').settings
    for setting in ('OPENTRACING_TRACE_ALL', 'OPENTRACING_TRACED_ATTRIBUTES',
                    'OPENTRACING_TRACER_CALLABLE',
                    'OPENTRACING_TRACER_PARAMETERS',
                    'OPENTRACING_SET_GLOBAL_TRACER', 'OPENTRACING_TRACING',
                    'OPENTRACING_TRACER'):
        try:
            delattr(settings, setting)
        except AttributeError:
            pass

    middleware, setting = get_middleware_and_setting_name()
    middleware_classes = [
        i for i in middleware if i != config.middleware_class
    ]
    setattr(settings, setting, middleware_classes)
    utils.mark_uninstrumented(django)
Example #13
0
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)
Example #14
0
    def test_env_var_disables_instrument(self, env_var, are_uninstrumented):
        os.environ[tracing_enabled_env_var] = env_var
        try:
            modules = [
                utils.get_module(l) for l in expected_traceable_libraries
            ]
            assert self.all_are_uninstrumented(modules)

            for m in expected_traceable_libraries:
                instrument(**{m: True})

            assert self.all_are_uninstrumented(modules) is are_uninstrumented
        finally:
            os.environ.pop(tracing_enabled_env_var)
Example #15
0
    def test_env_var_disables_prevents_auto_instrument(self, env_var,
                                                       are_uninstrumented):
        os.environ[tracing_enabled_env_var] = env_var
        try:
            modules = [
                utils.get_module(l)
                for l in expected_auto_instrumentable_libraries
            ]
            assert self.all_are_uninstrumented(modules)

            auto_instrument()

            assert self.all_are_uninstrumented(modules) is are_uninstrumented
        finally:
            os.environ.pop(tracing_enabled_env_var)
Example #16
0
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):
    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):
    """
    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)
Example #19
0
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 uninstrument():
    requests = utils.get_module('requests')
    if not utils.is_instrumented(requests):
        return

    from requests_opentracing import SessionTracing

    if _session_tracing_new[0] is not None:
        if hasattr(_session_tracing_new[0], '__get__'):
            SessionTracing.__new__ = _session_tracing_new[0].__get__(SessionTracing)
        else:  # builtin doesn't follow descriptor protocol
            SessionTracing.__new__ = _session_tracing_new[0]
    if _session_new[0] is not None:
        if hasattr(_session_new[0], '__get__'):
            requests.Session.__new__ = _session_new[0].__get__(requests.Session)
        else:
            requests.Session.__new__ = _session_new[0]

    utils.revert_wrapper(SessionTracing, '__init__')
    utils.mark_uninstrumented(requests)
Example #21
0
    def test_instrumentation_env_var_disabled_prevents_auto_instrument(
            self, env_var, are_uninstrumented):
        enableds = [
            'SIGNALFX_{0}_ENABLED'.format(lib.upper())
            for lib in expected_auto_instrumentable_libraries
        ]
        for enabled in enableds:
            os.environ[enabled] = env_var
        try:
            modules = [
                utils.get_module(l)
                for l in expected_auto_instrumentable_libraries
            ]
            assert self.all_are_uninstrumented(modules)

            auto_instrument()

            assert self.all_are_uninstrumented(modules) is are_uninstrumented
        finally:
            for enabled in enableds:
                os.environ.pop(enabled)
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)
Example #23
0
def uninstrument():
    celery = utils.get_module('celery')
    if not utils.is_instrumented(celery):
        return

    import celery.app

    from celery_opentracing import CeleryTracing

    if _celery_tracing_new[0] is not None:
        if hasattr(_celery_tracing_new[0], '__get__'):
            CeleryTracing.__new__ = _celery_tracing_new[0].__get__(
                CeleryTracing)
        else:  # builtin doesn't follow descriptor protocol
            CeleryTracing.__new__ = _celery_tracing_new[0]
    if _celery_new[0] is not None:
        if hasattr(_celery_new[0], '__get__'):
            celery.app.base.Celery.__new__ = _celery_new[0].__get__(
                celery.Celery)
        else:
            celery.app.base.Celery.__new__ = _celery_new[0]

    utils.revert_wrapper(CeleryTracing, '__init__')
    utils.mark_uninstrumented(celery)
Example #24
0
 def test_instrument_with_true_instruments_specified_libraries(self):
     tornado = utils.get_module('tornado')
     assert not hasattr(tornado, instrumented_attr)
     instrument(tornado=True)
     assert getattr(tornado, instrumented_attr) is True
    @worker_process_init.connect(weak=False)
    def create_global_tracer(*args, **kwargs):
        tracer = create_tracer(access_token=access_token, set_global=False)
        tracer_proxy.set_tracer(tracer)


if hasattr(sys, 'argv') and sys.argv[0].split(
        os.path.sep)[-1] == 'celery' and 'worker' in sys.argv:
    create_celery_tracer()
else:
    try:
        auto_instrument(
            create_tracer(access_token=access_token, set_global=True))
    except Exception:
        print(traceback.format_exc())

# Do not prevent existing sitecustomize module import. Done by
# removing this module's package and attempting to import
# sitecustomize module.

# Removing references to this sitecustomize module
# can trigger garbage collection and cause lookup failures in other modules.
sys.modules['sfx_sitecustomize'] = sys.modules.pop('sitecustomize', None)
sys.path.remove(os.path.abspath(os.path.dirname(__file__)))

# Attempt to load any existing sitecustomize
module = get_module('sitecustomize')
if module is None:  # reset to our own if no preexisting
    sys.modules['sitecustomize'] = sys.modules['sfx_sitecustomize']
Example #26
0
 def test_uninstrument_uninstruments_specified_libraries(self, module_name):
     instrument(**{module_name: True})
     mod = utils.get_module(module_name)
     assert getattr(mod, instrumented_attr) is True
     uninstrument(module_name)
     assert not hasattr(mod, instrumented_attr)
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)
Example #28
0
def test_get_module_is_none_for_unavailable_modules():
    assert utils.get_module('not_a_real_module_12345') is None