コード例 #1
0
 def test_default_provider_set(self):
     # The Context Provider can set the current active Context;
     # this could happen in distributed tracing
     ctx = Context(trace_id=42, span_id=100)
     self.tracer.context_provider.activate(ctx)
     span = self.trace('web.request')
     span.assert_matches(name='web.request', trace_id=42, parent_id=100)
コード例 #2
0
    def test_get_report_hostname_default(self, get_hostname):
        get_hostname.return_value = 'test-hostname'

        # Create a context and add a span and finish it
        ctx = Context()
        span = Span(tracer=None, name='fake_span')
        ctx.add_span(span)
        span.finish()

        # Assert that we have not added the tag to the span yet
        assert span.get_tag(HOSTNAME_KEY) is None

        # Assert that retrieving the trace does not set the tag
        trace, _ = ctx.get()
        assert trace[0].get_tag(HOSTNAME_KEY) is None
        assert span.get_tag(HOSTNAME_KEY) is None
コード例 #3
0
    def test_set_context(self):
        # the Context can be set in the current Thread
        ctx = Context()
        ctxm = DefaultContextManager()
        assert ctxm.get() is not ctx

        ctxm.set(ctx)
        assert ctxm.get() is ctx
コード例 #4
0
    def test_get_report_hostname_disabled(self, get_hostname):
        get_hostname.return_value = 'test-hostname'

        with self.override_global_config(dict(report_hostname=False)):
            # Create a context and add a span and finish it
            ctx = Context()
            span = Span(tracer=None, name='fake_span')
            ctx.add_span(span)
            span.finish()

            # Assert that we have not added the tag to the span yet
            assert span.get_tag(HOSTNAME_KEY) is None

            # Assert that retrieving the trace does not set the tag
            trace, _ = ctx.get()
            assert trace[0].get_tag(HOSTNAME_KEY) is None
            assert span.get_tag(HOSTNAME_KEY) is None
コード例 #5
0
 def test_close_span(self):
     # it should keep track of closed spans, moving
     # the current active to it's parent
     ctx = Context()
     span = Span(tracer=None, name='fake_span')
     ctx.add_span(span)
     ctx.close_span(span)
     assert ctx.get_current_span() is None
コード例 #6
0
    def test_propagation_without_stack_context(self):
        # a Context is discarded if not set inside a TracerStackContext
        ctx = Context(trace_id=100, span_id=101)
        self.tracer.context_provider.activate(ctx)
        with self.tracer.trace('tornado'):
            sleep(0.01)

        traces = self.tracer.writer.pop_traces()
        assert len(traces) == 1
        assert len(traces[0]) == 1
        assert traces[0][0].trace_id != 100
        assert traces[0][0].parent_id != 101
コード例 #7
0
    def test_partial_flush_too_many(self):
        """
        When calling `Context.get`
            When partial flushing is enabled
            When we have more than the minimum number of spans needed to flush
                We return the finished spans
        """
        tracer = get_dummy_tracer()
        ctx = Context()

        # Create a root span with 5 children, all of the children are finished, the root is not
        root = Span(tracer=tracer, name='root')
        ctx.add_span(root)
        for i in range(5):
            child = Span(tracer=tracer,
                         name='child_{}'.format(i),
                         trace_id=root.trace_id,
                         parent_id=root.span_id)
            child._parent = root
            child.finished = True
            ctx.add_span(child)
            ctx.close_span(child)

        with self.override_partial_flush(ctx, enabled=True, min_spans=1):
            trace, sampled = ctx.get()

        self.assertIsNotNone(trace)
        self.assertIsNotNone(sampled)

        self.assertEqual(len(trace), 5)
        self.assertEqual(
            set(['child_0', 'child_1', 'child_2', 'child_3', 'child_4']),
            set([span.name for span in trace]))

        # Ensure we clear/reset internal stats as expected
        self.assertEqual(ctx._trace, [root])
        with self.override_partial_flush(ctx, enabled=True, min_spans=5):
            trace, sampled = ctx.get()
            self.assertIsNone(trace)
            self.assertIsNone(sampled)
コード例 #8
0
 def test_log_unfinished_spans_disabled(self, log):
     # the trace finished status logging is disabled
     tracer = get_dummy_tracer()
     ctx = Context()
     # manually create a root-child trace
     root = Span(tracer=tracer, name='root')
     child_1 = Span(tracer=tracer,
                    name='child_1',
                    trace_id=root.trace_id,
                    parent_id=root.span_id)
     child_2 = Span(tracer=tracer,
                    name='child_2',
                    trace_id=root.trace_id,
                    parent_id=root.span_id)
     child_1._parent = root
     child_2._parent = root
     ctx.add_span(root)
     ctx.add_span(child_1)
     ctx.add_span(child_2)
     # close only the parent
     root.finish()
     # the logger has never been invoked to print unfinished spans
     for call, _ in log.call_args_list:
         msg = call[0]
         assert 'the trace has %d unfinished spans' not in msg
コード例 #9
0
def test_log_unfinished_spans(log, tracer_with_debug_logging):
    # when the root parent is finished, notify if there are spans still pending
    tracer = tracer_with_debug_logging
    ctx = Context()
    # manually create a root-child trace
    root = Span(tracer=tracer, name='root')
    child_1 = Span(tracer=tracer,
                   name='child_1',
                   trace_id=root.trace_id,
                   parent_id=root.span_id)
    child_2 = Span(tracer=tracer,
                   name='child_2',
                   trace_id=root.trace_id,
                   parent_id=root.span_id)
    child_1._parent = root
    child_2._parent = root
    ctx.add_span(root)
    ctx.add_span(child_1)
    ctx.add_span(child_2)
    # close only the parent
    root.finish()
    unfinished_spans_log = log.call_args_list[-3][0][2]
    child_1_log = log.call_args_list[-2][0][1]
    child_2_log = log.call_args_list[-1][0][1]
    assert 2 == unfinished_spans_log
    assert 'name child_1' in child_1_log
    assert 'name child_2' in child_2_log
    assert 'duration 0.000000s' in child_1_log
    assert 'duration 0.000000s' in child_2_log
コード例 #10
0
    def test_partial_flush_remaining(self):
        """
        When calling `Context.get`
            When partial flushing is enabled
            When we have some unfinished spans
                We keep the unfinished spans around
        """
        tracer = get_dummy_tracer()
        ctx = Context()

        # Create a root span with 5 children, all of the children are finished, the root is not
        root = Span(tracer=tracer, name='root')
        ctx.add_span(root)
        for i in range(10):
            child = Span(tracer=tracer,
                         name='child_{}'.format(i),
                         trace_id=root.trace_id,
                         parent_id=root.span_id)
            child._parent = root
            ctx.add_span(child)

            # CLose the first 5 only
            if i < 5:
                child.finished = True
                ctx.close_span(child)

        with self.override_partial_flush(ctx, enabled=True, min_spans=5):
            trace, sampled = ctx.get()

        # Assert partially flushed spans
        self.assertTrue(len(trace), 5)
        self.assertIsNotNone(sampled)
        self.assertEqual(
            set(['child_0', 'child_1', 'child_2', 'child_3', 'child_4']),
            set([span.name for span in trace]))

        # Assert remaining unclosed spans
        self.assertEqual(len(ctx._trace), 6)
        self.assertEqual(
            set([
                'root', 'child_5', 'child_6', 'child_7', 'child_8', 'child_9'
            ]),
            set([span.name for span in ctx._trace]),
        )
コード例 #11
0
    def test_propagation_with_new_context(self):
        # inside a TracerStackContext it should be possible to set
        # a new Context for distributed tracing
        with TracerStackContext():
            ctx = Context(trace_id=100, span_id=101)
            self.tracer.context_provider.activate(ctx)
            with self.tracer.trace('tornado'):
                sleep(0.01)

        traces = self.tracer.writer.pop_traces()
        assert len(traces) == 1
        assert len(traces[0]) == 1
        assert traces[0][0].trace_id == 100
        assert traces[0][0].parent_id == 101
コード例 #12
0
    def test_set_tag_manual_drop(self):
        ctx = Context()
        s = Span(tracer=None, name='root.span', service='s', resource='r', context=ctx)

        assert s.context == ctx
        assert ctx.sampling_priority != priority.USER_REJECT
        assert s.context.sampling_priority != priority.USER_REJECT
        assert s.meta == dict()

        s.set_tag('manual.drop')
        assert ctx.sampling_priority == priority.USER_REJECT
        assert s.context.sampling_priority == priority.USER_REJECT
        assert s.meta == dict()

        ctx.sampling_priority = priority.AUTO_REJECT
        assert ctx.sampling_priority == priority.AUTO_REJECT
        assert s.context.sampling_priority == priority.AUTO_REJECT
        assert s.meta == dict()

        s.set_tag('manual.drop')
        assert ctx.sampling_priority == priority.USER_REJECT
        assert s.context.sampling_priority == priority.USER_REJECT
        assert s.meta == dict()
コード例 #13
0
 def test_clone(self):
     ctx = Context()
     ctx.sampling_priority = 2
     # manually create a root-child trace
     root = Span(tracer=None, name='root')
     child = Span(tracer=None,
                  name='child_1',
                  trace_id=root.trace_id,
                  parent_id=root.span_id)
     child._parent = root
     ctx.add_span(root)
     ctx.add_span(child)
     cloned_ctx = ctx.clone()
     assert cloned_ctx._parent_trace_id == ctx._parent_trace_id
     assert cloned_ctx._parent_span_id == ctx._parent_span_id
     assert cloned_ctx._sampling_priority == ctx._sampling_priority
     assert cloned_ctx._otel_origin == ctx._otel_origin
     assert cloned_ctx._current_span == ctx._current_span
     assert cloned_ctx._trace == []
コード例 #14
0
    def test_propagation_with_new_context(self):
        # create multiple futures so that we expect multiple
        # traces instead of a single one
        ctx = Context(trace_id=100, span_id=101)
        self.tracer.context_provider.activate(ctx)

        def greenlet():
            with self.tracer.trace('greenlet'):
                gevent.sleep(0.01)

        jobs = [gevent.spawn(greenlet) for x in range(1)]
        gevent.joinall(jobs)

        traces = self.tracer.writer.pop_traces()
        assert 1 == len(traces)
        assert 1 == len(traces[0])
        assert traces[0][0].trace_id == 100
        assert traces[0][0].parent_id == 101
コード例 #15
0
    def test_thread_safe(self):
        # the Context must be thread-safe
        ctx = Context()

        def _fill_ctx():
            span = Span(tracer=None, name='fake_span')
            ctx.add_span(span)

        threads = [threading.Thread(target=_fill_ctx) for _ in range(100)]

        for t in threads:
            t.daemon = True
            t.start()

        for t in threads:
            t.join()

        assert 100 == len(ctx._trace)
コード例 #16
0
 def test_context_priority(self):
     # a context is sampled if the spans are sampled
     ctx = Context()
     for priority in [
             USER_REJECT, AUTO_REJECT, AUTO_KEEP, USER_KEEP, None, 999
     ]:
         ctx.sampling_priority = priority
         span = Span(tracer=None, name=('fake_span_%s' % repr(priority)))
         ctx.add_span(span)
         span.finish()
         # It's "normal" to have sampled be true even when priority sampling is
         # set to 0 or -1. It would stay false even even with priority set to 2.
         # The only criteria to send (or not) the spans to the agent should be
         # this "sampled" attribute, as it's tightly related to the trace weight.
         assert priority == ctx.sampling_priority
         trace, sampled = ctx.get()
         assert sampled is True, 'priority has no impact on sampled status'
コード例 #17
0
 def test_log_unfinished_spans_when_ok(self, log):
     # if the unfinished spans logging is enabled but the trace is finished, don't log anything
     tracer = get_dummy_tracer()
     ctx = Context()
     # manually create a root-child trace
     root = Span(tracer=tracer, name='root')
     child = Span(tracer=tracer,
                  name='child_1',
                  trace_id=root.trace_id,
                  parent_id=root.span_id)
     child._parent = root
     ctx.add_span(root)
     ctx.add_span(child)
     # close the trace
     child.finish()
     root.finish()
     # the logger has never been invoked to print unfinished spans
     for call, _ in log.call_args_list:
         msg = call[0]
         assert 'the trace has %d unfinished spans' not in msg
コード例 #18
0
    def test__span_to_otel_span(self):
        api = APIOtel(exporter=None)

        trace_id = 0x32452526
        span_id = 0x29025326
        parent_id = 0x592153109

        start_time = 683647322
        end_time = start_time + 50

        ctx = Context()
        span = Span(
            tracer=None,
            name='test_span',
            trace_id=trace_id,
            span_id=span_id,
            parent_id=parent_id,
            context=ctx,
            start=start_time,
            resource='foo_resource',
            service='foo_service',
            span_type='foo_span',
        )

        span.finish(finish_time=end_time)

        span.set_tag('out.host', 'opentelemetry.io')
        span.set_tag('out.port', 443)
        span.set_tag('creator_name', 'mauricio.vasquez')

        otel_span = api._span_to_otel_span(span)

        self.assertEqual(span.name, otel_span.name)

        self.assertEqual(span.trace_id, otel_span.context.trace_id)
        self.assertEqual(span.span_id, otel_span.context.span_id)

        self.assertEqual(span.parent_id, otel_span.parent.span_id)
        self.assertEqual(span.trace_id, otel_span.parent.trace_id)

        self.assertEqual(start_time * 10**9, otel_span.start_time)
        self.assertEqual(end_time * 10**9, otel_span.end_time)

        self.assertEqual(span.service, otel_span.attributes['service.name'])
        self.assertEqual(span.resource, otel_span.attributes['resource.name'])
        self.assertEqual(span.span_type, otel_span.attributes['component'])

        self.assertEqual(span.get_tag('out.host'),
                         otel_span.attributes['peer.hostname'])
        self.assertEqual(span.get_tag('out.port'),
                         otel_span.attributes['peer.port'])

        self.assertEqual(span.get_tag('creator_name'),
                         otel_span.attributes['creator_name'])

        # test parent None

        span = Span(
            tracer=None,
            name='test_span',
            trace_id=trace_id,
            span_id=span_id,
            parent_id=None,
            context=ctx,
            start=start_time,
        )

        span.finish(finish_time=end_time)

        otel_span = api._span_to_otel_span(span)

        self.assertIsNone(otel_span.parent)
コード例 #19
0
 def test_finished(self):
     # a Context is finished if all spans inside are finished
     ctx = Context()
     span = Span(tracer=None, name='fake_span')
     ctx.add_span(span)
     ctx.close_span(span)
コード例 #20
0
 def test_current_root_span_none(self):
     # it should return none when there is no root span
     ctx = Context()
     assert ctx.get_current_root_span() is None
コード例 #21
0
 def test_current_root_span(self):
     # it should return the current active root span
     ctx = Context()
     span = Span(tracer=None, name='fake_span')
     ctx.add_span(span)
     assert span == ctx.get_current_root_span()
コード例 #22
0
 def test_set_call_context(self):
     # a different Context is set for the current logical execution
     task = asyncio.Task.current_task()
     ctx = Context()
     helpers.set_call_context(task, ctx)
     assert ctx == self.tracer.get_call_context()