def _new_span(self, name): tracer = FakeTrace(ip_address='127.0.0.1', service_name='reporter_test') span = Span(trace_id=1, span_id=1, parent_id=None, flags=1, tracer=tracer, operation_name=name) span.start_time = time.time() span.end_time = span.start_time + 0.001 # 1ms return span
def test_context_to_readable_headers(self): codec = TextCodec(trace_id_header='Trace_ID', baggage_header_prefix='Trace-Attr-') span = Span(trace_id=256, span_id=127, parent_id=None, flags=1, operation_name='x', tracer=None, start_time=1) carrier = {} codec.inject(span, carrier) assert carrier == {'trace-id': '100:7f:0:1'} span.set_baggage_item('Fry', 'Leela') span.set_baggage_item('Bender', 'Countess de la Roca') carrier = {} codec.inject(span, carrier) assert carrier == { 'trace-id': '100:7f:0:1', 'trace-attr-bender': 'Countess de la Roca', 'trace-attr-fry': 'Leela'}
def test_zipkin_codec_inject(self): codec = ZipkinCodec() with self.assertRaises(InvalidCarrierException): codec.inject(span_context=None, carrier=[]) ctx = SpanContext(trace_id=256, span_id=127, parent_id=None, flags=1) span = Span(context=ctx, operation_name='x', tracer=None, start_time=1) carrier = {} codec.inject(span_context=span, carrier=carrier) assert carrier == {'span_id': 127, 'parent_id': None, 'trace_id': 256, 'traceflags': 1}
def test_zipkin_b3_codec_extract_injected(self): codec = B3Codec() ctx = SpanContext(trace_id=256, span_id=127, parent_id=None, flags=0) span = Span(context=ctx, operation_name='x', tracer=None, start_time=1) carrier = {} codec.inject(span_context=span, carrier=carrier) extracted = codec.extract(carrier) assert extracted.trace_id == ctx.trace_id assert extracted.span_id == ctx.span_id assert extracted.parent_id == ctx.parent_id assert extracted.flags == ctx.flags
def test_baggage_logs(): mock_tracer = mock.MagicMock() mock_tracer.max_tag_value_length = 100 ctx = SpanContext(trace_id=1, span_id=2, parent_id=None, flags=1) span = Span(context=ctx, operation_name='x', tracer=mock_tracer) span.set_baggage_item('x', 'a') assert span.get_baggage_item('x') == 'a' assert len(span.logs) == 1 assert _fields_to_dict(span.logs[0]) == { 'event': 'baggage', 'key': 'x', 'value': 'a', } span.set_baggage_item('x', 'b') # override assert span.get_baggage_item('x') == 'b' assert len(span.logs) == 2 assert _fields_to_dict(span.logs[1]) == { 'event': 'baggage', 'key': 'x', 'value': 'b', 'override': 'true', } span.set_baggage_item('x', None) # deletion assert span.get_baggage_item('x') is None assert len(span.logs) == 3 assert _fields_to_dict(span.logs[2]) == { 'event': 'baggage', 'key': 'x', 'value': 'None', 'override': 'true' }
def test_zipkin_b3_codec_inject(self): codec = B3Codec() with self.assertRaises(InvalidCarrierException): codec.inject(span_context=None, carrier=[]) ctx = SpanContext(trace_id=256, span_id=127, parent_id=None, flags=1) span = Span(context=ctx, operation_name='x', tracer=None, start_time=1) carrier = {} codec.inject(span_context=span, carrier=carrier) assert carrier == { 'X-B3-SpanId': format(127, 'x').zfill(16), 'X-B3-TraceId': format(256, 'x').zfill(16), 'X-B3-Flags': '1' }
def test_traceback_cut(): """Test that a traceback is cut off at max_tag_value_length""" mock_tracer = mock.MagicMock() mock_tracer.max_tag_value_length = 300 mock_tracer.max_traceback_length = 5 context = SpanContext(trace_id=1, span_id=2, parent_id=None, flags=1) span = Span(context=context, operation_name='traceback_test', tracer=mock_tracer) try: with span: raise ValueError('Something unexpected happened!') except ValueError: fields_dict = {field.key: field.vStr for field in span.logs[0].fields} assert 'stack' in fields_dict stack_message = fields_dict['stack'] assert stack_message == ' Fil'
def test_baggage_logs(): mock_tracer = mock.MagicMock() mock_tracer.max_tag_value_length = 100 ctx = SpanContext(trace_id=1, span_id=2, parent_id=None, flags=1) span = Span(context=ctx, operation_name='x', tracer=mock_tracer) span.set_baggage_item('x', 'a') assert span.get_baggage_item('x') == 'a' assert len(span.logs) == 1 assert _fields_to_dict(span.logs[0]) == { "event": "baggage", "key": "x", "value": "a", } span.set_baggage_item('x', 'b') # override assert span.get_baggage_item('x') == 'b' assert len(span.logs) == 2 assert _fields_to_dict(span.logs[1]) == { "event": "baggage", "key": "x", "value": "b", "override": "true", }
def test_inject_with_128bit_trace_id(tracer, fmt, carrier, get_trace_id): tracer_128bit = Tracer(service_name='test', reporter=InMemoryReporter(), sampler=ConstSampler(True), generate_128bit_trace_id=True) for tracer in [tracer, tracer_128bit]: length = tracer.max_trace_id_bits / 4 trace_id = (1 << 64) - 1 if length == 16 else (1 << 128) - 1 ctx = SpanContext(trace_id=trace_id, span_id=127, parent_id=None, flags=1) span = Span(ctx, operation_name='test-%s' % fmt, tracer=None, start_time=1) tracer.inject(span, fmt, carrier) assert len(get_trace_id(carrier)) == length # test if the trace_id arrived on wire remains same even if # the tracer is configured for 64bit ids or 128bit ids ctx = SpanContext(trace_id=(1 << 128) - 1, span_id=127, parent_id=None, flags=0) span = tracer.start_span('test-%s' % fmt, child_of=ctx) carrier = dict() tracer.inject(span, fmt, carrier) assert len(get_trace_id(carrier)) == 32 ctx = SpanContext(trace_id=(1 << 64) - 1, span_id=127, parent_id=None, flags=0) span = tracer.start_span('test-%s' % fmt, child_of=ctx) carrier = dict() tracer.inject(span, fmt, carrier) assert len(get_trace_id(carrier)) == 16
def test_traceback(): """Test that a traceback is logged with both location and message""" mock_tracer = mock.MagicMock() mock_tracer.max_tag_value_length = 300 mock_tracer.max_traceback_length = 300 context = SpanContext(trace_id=1, span_id=2, parent_id=None, flags=1) span = Span(context=context, operation_name='traceback_test', tracer=mock_tracer) try: with span: raise ValueError('Something unexpected happened!') except ValueError: fields_dict = {field.key: field.vStr for field in span.logs[0].fields} assert 'stack' in fields_dict stack_message = fields_dict['stack'] stack_message_lines = stack_message.splitlines() assert len(stack_message_lines) == 2 assert stack_message_lines[0].startswith(' File ') assert stack_message_lines[1] == \ " raise ValueError('Something unexpected happened!')"
def test_baggage(): mock_tracer = mock.MagicMock() mock_tracer.max_tag_value_length = 100 ctx = SpanContext(trace_id=1, span_id=2, parent_id=None, flags=1) span = Span(context=ctx, operation_name='x', tracer=mock_tracer) assert span.get_baggage_item('x') is None span.set_baggage_item('x', 'y').\ set_baggage_item('z', 'why') assert span.get_baggage_item('x') == 'y' assert span.get_baggage_item('z') == 'why' assert span.get_baggage_item('tt') is None assert len(span.context.baggage) == 2 span.set_baggage_item('x', 'b') # override assert span.get_baggage_item('x') == 'b' assert len(span.context.baggage) == 2 span.set_baggage_item('X_y', '123') assert span.get_baggage_item('X_y') == '123' assert span.get_baggage_item('x-Y') is None span.set_baggage_item('nonExistingKey', None).set_baggage_item('z', None) assert 'z' not in span.context.baggage
def test_span_to_string(tracer): tracer.service_name = 'unittest' ctx = SpanContext(trace_id=1, span_id=1, parent_id=1, flags=1) span = Span(context=ctx, operation_name='crypt', tracer=tracer) assert '%s' % span == '1:1:1:1 unittest.crypt'
span.log_kv({'span.trace_id': span.trace_id, 'span.span_id': span.span_id, 'span.parent_id': span.parent_id, 'span.operation_name': span.operation_name, }) with tracer.start_span('ChildSpan', child_of=span) as child_span: child_span.log_kv({'span.trace_id': child_span.trace_id, 'child_span.span_id': child_span.span_id, 'child_span.parent_id': child_span.parent_id, 'child_span.operation_name': child_span.operation_name, }) ctx = SpanContext(trace_id=child_span.trace_id, span_id=span_id1, parent_id=child_span.span_id, flags=1) span1 = Span(context=ctx, operation_name='ChildSpanChildSpan', tracer=tracer) span1.log_kv({'event': 'ChildSpanChildSpan', }) span1.finish() child_span.log_kv({'span.trace_id': child_span.trace_id, 'child_span.span_id': child_span.span_id, 'child_span.parent_id': child_span.parent_id, 'child_span.operation_name': child_span.operation_name, }) span.log_kv({'span.trace_id': span.trace_id, 'span.span_id': span.span_id, 'span.parent_id': span.parent_id, 'span.operation_name': span.operation_name, })
def test_baggage(): ctx = SpanContext(trace_id=1, span_id=2, parent_id=None, flags=1) span = Span(context=ctx, operation_name='x', tracer=None) assert span.get_baggage_item('x') is None span.set_baggage_item('x', 'y').\ set_baggage_item('z', 'why') assert span.get_baggage_item('x') == 'y' assert span.get_baggage_item('z') == 'why' assert span.get_baggage_item('tt') is None assert len(span.context.baggage) == 2 span.set_baggage_item('x', 'b') # override assert span.get_baggage_item('x') == 'b' assert len(span.context.baggage) == 2 span.set_baggage_item('X_y', '123') assert span.get_baggage_item('X_y') == '123' assert span.get_baggage_item('x-Y') is None
def span_setup(span: Span, message: any): if message is not None: span.log_kv({'message': str(message)})
def test_is_rpc(): mock_tracer = mock.MagicMock() mock_tracer.max_tag_value_length = 100 ctx = SpanContext(trace_id=1, span_id=2, parent_id=None, flags=1) span = Span(context=ctx, operation_name='x', tracer=mock_tracer) assert span.is_rpc() is False assert span.is_rpc_client() is False span = Span(context=ctx, operation_name='x', tracer=mock_tracer) span.set_tag(ext_tags.SPAN_KIND, ext_tags.SPAN_KIND_RPC_SERVER) assert span.is_rpc() is True assert span.is_rpc_client() is False span = Span(context=ctx, operation_name='x', tracer=mock_tracer) span.set_tag(ext_tags.SPAN_KIND, ext_tags.SPAN_KIND_RPC_CLIENT) assert span.is_rpc() is True assert span.is_rpc_client() is True
def start_span(self, operation_name=None, child_of=None, references=None, tags=None, start_time=None): """ Start and return a new Span representing a unit of work. :param operation_name: name of the operation represented by the new span from the perspective of the current service. :param child_of: shortcut for 'child_of' reference :param references: (optional) either a single Reference object or a list of Reference objects that identify one or more parent SpanContexts. (See the Reference documentation for detail) :param tags: optional dictionary of Span Tags. The caller gives up ownership of that dictionary, because the Tracer may use it as-is to avoid extra data copying. :param start_time: an explicit Span start time as a unix timestamp per time.time() :return: Returns an already-started Span instance. """ parent = child_of if references: if isinstance(references, list): # TODO(XXX) only the first reference is currently used references = references[0] parent = references.referenced_context # allow Span to be passed as reference, not just SpanContext if isinstance(parent, Span): parent = parent.context rpc_server = tags and \ tags.get(ext_tags.SPAN_KIND) == ext_tags.SPAN_KIND_RPC_SERVER if parent is None or parent.is_debug_id_container_only: trace_id = self.random_trace_id() span_id = self.random_id() parent_id = None flags = 0 baggage = None if parent is None: sampled, sampler_tags = \ self.sampler.is_sampled(trace_id, operation_name) if sampled: flags = SAMPLED_FLAG tags = tags or {} for k, v in six.iteritems(sampler_tags): tags[k] = v else: # have debug id flags = SAMPLED_FLAG | DEBUG_FLAG tags = tags or {} tags[self.debug_id_header] = parent.debug_id else: trace_id = parent.trace_id if rpc_server and self.one_span_per_rpc: # Zipkin-style one-span-per-RPC span_id = parent.span_id parent_id = parent.parent_id else: span_id = self.random_id() parent_id = parent.span_id flags = parent.flags baggage = dict(parent.baggage) span_ctx = SpanContext(trace_id=trace_id, span_id=span_id, parent_id=parent_id, flags=flags, baggage=baggage) span = Span(context=span_ctx, tracer=self, operation_name=operation_name, tags=tags, start_time=start_time) if (rpc_server or not parent_id) and (flags & SAMPLED_FLAG): # this is a first-in-process span, and is sampled for k, v in six.iteritems(self.tags): span.set_tag(k, v) self._emit_span_metrics(span=span, join=rpc_server) return span