Beispiel #1
0
    def test_cache_add_without_arguments(self):
        # initialize the dummy writer
        writer = DummyWriter()
        tracer = Tracer()
        tracer.writer = writer

        # create the TracedCache instance for a Flask app
        Cache = get_traced_cache(tracer, service=self.SERVICE)
        app = Flask(__name__)
        cache = Cache(app, config={'CACHE_TYPE': 'simple'})

        # make a wrong call
        with pytest.raises(TypeError) as ex:
            cache.add()

        # ensure that the error is not caused by our tracer
        assert 'add()' in ex.value.args[0]
        assert 'argument' in ex.value.args[0]
        spans = writer.pop()
        # an error trace must be sent
        assert len(spans) == 1
        span = spans[0]
        assert span.service == self.SERVICE
        assert span.resource == 'add'
        assert span.name == 'flask_cache.cmd'
        assert span.span_type == 'cache'
        assert span.error == 1
Beispiel #2
0
    def test_memcached_cache_tracing_with_a_wrong_connection(self):
        # initialize the dummy writer
        writer = DummyWriter()
        tracer = Tracer()
        tracer.writer = writer

        # create the TracedCache instance for a Flask app
        Cache = get_traced_cache(tracer, service=self.SERVICE)
        app = Flask(__name__)
        config = {
            'CACHE_TYPE': 'memcached',
            'CACHE_MEMCACHED_SERVERS': ['localhost:2230'],
        }
        cache = Cache(app, config=config)

        # use a wrong memcached connection
        try:
            cache.get(u'á_complex_operation')
        except Exception:
            pass

        # ensure that the error is not caused by our tracer
        spans = writer.pop()
        assert len(spans) == 1
        span = spans[0]
        assert span.service == self.SERVICE
        assert span.resource == 'get'
        assert span.name == 'flask_cache.cmd'
        assert span.span_type == 'cache'
        assert span.meta[CACHE_BACKEND] == 'memcached'
        assert span.meta[net.TARGET_HOST] == 'localhost'
        assert span.meta[net.TARGET_PORT] == '2230'
Beispiel #3
0
    def test_redis_cache_tracing_with_a_wrong_connection(self):
        # initialize the dummy writer
        writer = DummyWriter()
        tracer = Tracer()
        tracer.writer = writer

        # create the TracedCache instance for a Flask app
        Cache = get_traced_cache(tracer, service=self.SERVICE)
        app = Flask(__name__)
        config = {
            'CACHE_TYPE': 'redis',
            'CACHE_REDIS_PORT': 2230,
            'CACHE_REDIS_HOST': '127.0.0.1'
        }
        cache = Cache(app, config=config)

        # use a wrong redis connection
        with pytest.raises(ConnectionError) as ex:
            cache.get(u'á_complex_operation')

        # ensure that the error is not caused by our tracer
        assert '127.0.0.1:2230. Connection refused.' in ex.value.args[0]
        spans = writer.pop()
        # an error trace must be sent
        assert len(spans) == 1
        span = spans[0]
        assert span.service == self.SERVICE
        assert span.resource == 'get'
        assert span.name == 'flask_cache.cmd'
        assert span.span_type == 'cache'
        assert span.meta[CACHE_BACKEND] == 'redis'
        assert span.meta[net.TARGET_HOST] == '127.0.0.1'
        assert span.meta[net.TARGET_PORT] == '2230'
        assert span.error == 1
Beispiel #4
0
    def setUp(self):
        """
        Create a tracer with running workers, while spying the ``_put()`` method to
        keep trace of triggered API calls.
        """
        self.exporter = InMemorySpanExporter()
        api = APIOtel(exporter=self.exporter)

        # create a new tracer
        self.tracer = Tracer()
        self.tracer.configure(api=api)
        # spy the send() method
        self.api = self.tracer.writer.api
Beispiel #5
0
 def test_resource_from_cache_without_prefix(self):
     # create the TracedCache instance for a Flask app
     tracer = Tracer()
     Cache = get_traced_cache(tracer, service=self.SERVICE)
     app = Flask(__name__)
     traced_cache = Cache(app, config={'CACHE_TYPE': 'redis'})
     # expect only the resource name
     expected_resource = 'get'
     resource = _resource_from_cache_prefix('GET', traced_cache.config)
     assert resource == expected_resource
Beispiel #6
0
    def setUp(self):
        # backup previous conf
        self.backupEnabled = settings.ENABLED
        self.backupTracer = settings.TRACER

        # Use a new tracer to be sure that a new service
        # would be sent to the the writer
        self.tracer = Tracer()
        self.tracer.writer = DummyWriter()

        # Restart app with tracing disabled
        settings.ENABLED = False
        self.app = apps.get_app_config('opentelemetry_django')
        self.app.ready()
Beispiel #7
0
 def test_resource_from_cache_with_prefix(self):
     # create the TracedCache instance for a Flask app
     tracer = Tracer()
     Cache = get_traced_cache(tracer, service=self.SERVICE)
     app = Flask(__name__)
     config = {
         'CACHE_TYPE': 'redis',
         'CACHE_REDIS_PORT': REDIS_CONFIG['port'],
         'CACHE_KEY_PREFIX': 'users',
     }
     traced_cache = Cache(app, config=config)
     # expect a resource with a prefix
     expected_resource = 'get users'
     resource = _resource_from_cache_prefix('GET', traced_cache.cache)
     assert resource == expected_resource
Beispiel #8
0
 def test_extract_redis_connection_metadata(self):
     # create the TracedCache instance for a Flask app
     tracer = Tracer()
     Cache = get_traced_cache(tracer, service=self.SERVICE)
     app = Flask(__name__)
     config = {
         'CACHE_TYPE': 'redis',
         'CACHE_REDIS_PORT': REDIS_CONFIG['port'],
     }
     traced_cache = Cache(app, config=config)
     # extract client data
     meta = _extract_conn_tags(traced_cache.cache._client)
     expected_meta = {
         'out.host': 'localhost',
         'out.port': REDIS_CONFIG['port'],
         'out.redis_db': 0
     }
     assert meta == expected_meta
Beispiel #9
0
 def test_extract_memcached_connection_metadata(self):
     # create the TracedCache instance for a Flask app
     tracer = Tracer()
     Cache = get_traced_cache(tracer, service=self.SERVICE)
     app = Flask(__name__)
     config = {
         'CACHE_TYPE':
         'memcached',
         'CACHE_MEMCACHED_SERVERS':
         ['127.0.0.1:{}'.format(MEMCACHED_CONFIG['port'])],
     }
     traced_cache = Cache(app, config=config)
     # extract client data
     meta = _extract_conn_tags(traced_cache.cache._client)
     expected_meta = {
         'out.host': '127.0.0.1',
         'out.port': MEMCACHED_CONFIG['port']
     }
     assert meta == expected_meta
Beispiel #10
0
class TestWorkers(TestCase):
    """
    Ensures that a workers interacts correctly with the main thread. These are part
    of integration tests so real calls are triggered.
    """

    def setUp(self):
        """
        Create a tracer with running workers, while spying the ``_put()`` method to
        keep trace of triggered API calls.
        """
        self.exporter = InMemorySpanExporter()
        api = APIOtel(exporter=self.exporter)

        # create a new tracer
        self.tracer = Tracer()
        self.tracer.configure(api=api)
        # spy the send() method
        self.api = self.tracer.writer.api

    def tearDown(self):
        """
        Stop running worker
        """
        self._wait_thread_flush()

    def _wait_thread_flush(self):
        """
        Helper that waits for the thread flush
        """
        self.tracer.writer.stop()
        self.tracer.writer.join(None)

    def test_worker_single_trace(self):
        # create a trace block and send it using the transport system
        tracer = self.tracer
        tracer.trace('client.testing').finish()

        # one send is expected
        self._wait_thread_flush()

        spans = self.exporter.get_finished_spans()

        self.assertEqual(len(spans), 1)
        self.assertEqual(spans[0].name, 'client.testing')

    def test_worker_single_trace_multiple_spans(self):
        # make a single send() if a single trace with multiple spans is created before the flush
        tracer = self.tracer
        parent = tracer.trace('client.testing.parent')
        tracer.trace('client.testing.child').finish()
        parent.finish()

        # one send is expected
        self._wait_thread_flush()

        spans = self.exporter.get_finished_spans()

        self.assertEqual(len(spans), 2)
        self.assertEqual(spans[0].name, 'client.testing.parent')
        self.assertEqual(spans[1].name, 'client.testing.child')

    def test_worker_filter_request(self):
        self.tracer.configure(
            settings={FILTERS_KEY: [FilterRequestsOnUrl(r'http://example\.com/health')]},
            api=self.api,
        )

        span = self.tracer.trace('testing.filteredurl')
        span.set_tag(http.URL, 'http://example.com/health')
        span.finish()
        span = self.tracer.trace('testing.nonfilteredurl')
        span.set_tag(http.URL, 'http://example.com/api/resource')
        span.finish()
        self._wait_thread_flush()

        spans = self.exporter.get_finished_spans()

        self.assertEqual(len(spans), 1)
        self.assertEqual(spans[0].name, 'testing.nonfilteredurl')
# project
from oteltrace.tracer import Tracer
from oteltrace.contrib.django.conf import settings
from oteltrace.contrib.django.db import patch_db, unpatch_db
from oteltrace.contrib.django.cache import unpatch_cache
from oteltrace.contrib.django.templates import unpatch_template
from oteltrace.contrib.django.middleware import remove_exception_middleware, remove_trace_middleware

# testing
from ...base import BaseTestCase
from ...test_tracer import DummyWriter


# testing tracer
tracer = Tracer()
tracer.writer = DummyWriter()


class DjangoTraceTestCase(BaseTestCase, TestCase):
    """
    Base class that provides an internal tracer according to given
    OpenTelemetry settings. This class ensures that the tracer spans are
    properly reset after each run. The tracer is available in
    the ``self.tracer`` attribute.
    """
    def setUp(self):
        # assign the default tracer
        self.tracer = settings.TRACER
        # empty the tracer spans from previous operations
        # such as database creation queries