def test_context_sampled(self): # a context is sampled if the spans are sampled ctx = Context() span = Span(tracer=None, name='fake_span') ctx.add_span(span) ok_(ctx._sampled is True) ok_(ctx.sampling_priority is None)
def test_add_span(self): # it should add multiple spans ctx = Context() span = Span(tracer=None, name='fake_span') ctx.add_span(span) eq_(1, len(ctx._trace)) eq_('fake_span', ctx._trace[0].name) eq_(ctx, span.context)
def test_get_trace_empty(self): # it should return None if the Context is not finished ctx = Context() span = Span(tracer=None, name='fake_span') ctx.add_span(span) trace, sampled = ctx.get() ok_(trace is None) ok_(sampled is None)
def test_finish_called_multiple_times(): # we should only record a span the first time finish is called on it dt = DummyTracer() ctx = Context() s = Span(dt, 'bar', context=ctx) ctx.add_span(s) s.finish() s.finish() assert dt.spans_recorded == 1
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) # 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. ok_(ctx._sampled is True, 'priority has no impact on sampled status') eq_(priority, ctx.sampling_priority)
def test_finish(): # ensure finish will record a span dt = DummyTracer() ctx = Context() s = Span(dt, "test.span", context=ctx) ctx.add_span(s) assert s.duration is None sleep = 0.05 with s as s1: assert s is s1 time.sleep(sleep) assert s.duration >= sleep, "%s < %s" % (s.duration, sleep) eq_(1, dt.spans_recorded)
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() tracer.debug_logging = True 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] ok_('the trace has %d unfinished spans' not in msg)
def test_log_unfinished_spans(self, log): # when the root parent is finished, notify if there are spans still pending tracer = get_dummy_tracer() tracer.debug_logging = True 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() ok_(ctx.is_finished() is False) 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] eq_(2, unfinished_spans_log) ok_('name child_1' in child_1_log) ok_('name child_2' in child_2_log) ok_('duration 0.000000s' in child_1_log) ok_('duration 0.000000s' in child_2_log)
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) ok_(ctx.is_finished())
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) eq_(1, ctx._finished_spans) ok_(ctx.get_current_span() is None)
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() eq_(cloned_ctx._parent_trace_id, ctx._parent_trace_id) eq_(cloned_ctx._parent_span_id, ctx._parent_span_id) eq_(cloned_ctx._sampled, ctx._sampled) eq_(cloned_ctx._sampling_priority, ctx._sampling_priority) eq_(cloned_ctx._current_span, ctx._current_span) eq_(cloned_ctx._trace, []) eq_(cloned_ctx._finished_spans, 0)
def test_get_trace(self): # it should return the internal trace structure # if the context is finished ctx = Context() span = Span(tracer=None, name='fake_span') ctx.add_span(span) ctx.close_span(span) trace, sampled = ctx.get() eq_(1, len(trace)) eq_(span, trace[0]) ok_(sampled is True) # the context should be empty eq_(0, len(ctx._trace)) eq_(0, ctx._finished_spans) ok_(ctx._current_span is None) ok_(ctx._sampled is True)
def test_log_unfinished_spans_disabled(self, log): # the trace finished status logging is disabled tracer = get_dummy_tracer() tracer.debug_logging = False 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() ok_(ctx.is_finished() is False) # the logger has never been invoked to print unfinished spans for call, _ in log.call_args_list: msg = call[0] ok_('the trace has %d unfinished spans' not in msg)
def test_finished_empty(self): # a Context is not finished if it's empty ctx = Context() ok_(ctx.is_finished() is False)
def test_context_sampled(self): # a context is sampled if the spans are sampled ctx = Context() span = Span(tracer=None, name='fake_span') ctx.add_span(span) ok_(ctx._sampled is True)
def inject_new_context(self, *args, **kwargs): pin = Pin.get_from(self.app) pin.tracer.context_provider.activate( Context(trace_id=99999, span_id=99999, sampling_priority=1))
def setUp(self): super(CeleryDistributedTracingIntegrationTask, self).setUp() provider = Pin.get_from(self.app).tracer.context_provider provider.activate( Context(trace_id=12345, span_id=12345, sampling_priority=1))
def test_current_span(self): # it should return the current active span ctx = Context() span = Span(tracer=None, name='fake_span') ctx.add_span(span) eq_(span, ctx.get_current_span())
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)
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
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()