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
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
def test_finish_set_span_duration(self): # If set the duration on a span, the span should be recorded with this # duration s = Span(tracer=None, name='test.span') s.duration = 1337.0 s.finish() assert s.duration == 1337.0
def test_finish_called_multiple_times(self): # we should only record a span the first time finish is called on it ctx = Context() s = Span(self.tracer, 'bar', context=ctx) ctx.add_span(s) s.finish() s.finish() self.assert_span_count(1)
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) span.finish() trace, sampled = ctx.get() assert sampled is True assert ctx.sampling_priority is None
def test_span_boolean_err(self): s = Span(tracer=None, name='foo.bar', service='s', resource='r') s.error = True s.finish() d = s.to_dict() assert d assert d['error'] == 1 assert type(d['error']) == int
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) span.finish() trace, sampled = ctx.get() assert [span] == trace assert sampled is True # the context should be empty assert 0 == len(ctx._trace) assert ctx._current_span is None
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
def test_span_to_dict(self): s = Span(tracer=None, name='test.span', service='s', resource='r') s.span_type = 'foo' s.set_tag('a', '1') s.set_meta('b', '2') s.finish() d = s.to_dict() assert d assert d['span_id'] == s.span_id assert d['trace_id'] == s.trace_id assert d['parent_id'] == s.parent_id assert d['meta'] == {'a': '1', 'b': '2'} assert d['type'] == 'foo' assert d['error'] == 0 assert type(d['error']) == int
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
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'
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
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)
def test_finish_no_tracer(self): # ensure finish works with no tracer without raising exceptions s = Span(tracer=None, name='test.span') s.finish()