def format_span_json(span): """Helper to format a Span in JSON format. :type span: :class:`~opencensus.trace.span.Span` :param span: A Span to be transferred to JSON format. :rtype: dict :returns: Formatted Span. """ span_json = { 'displayName': utils.get_truncatable_str(span.name), 'spanId': span.span_id, 'startTime': span.start_time, 'endTime': span.end_time, 'childSpanCount': len(span._child_spans) } parent_span_id = None if span.parent_span is not None: parent_span_id = span.parent_span.span_id if parent_span_id is not None: span_json['parentSpanId'] = parent_span_id if span.attributes: span_json['attributes'] = attributes_module.Attributes( span.attributes).format_attributes_json() if span.stack_trace is not None: span_json['stackTrace'] = span.stack_trace.format_stack_trace_json() formatted_time_events = [] if span.annotations: formatted_time_events.extend({ 'time': aa.timestamp, 'annotation': aa.format_annotation_json() } for aa in span.annotations) if span.message_events: formatted_time_events.extend( { 'time': aa.timestamp, 'message_event': aa.format_message_event_json() } for aa in span.message_events) if formatted_time_events: span_json['timeEvents'] = {'timeEvent': formatted_time_events} if span.links: span_json['links'] = { 'link': [link.format_link_json() for link in span.links] } if span.status is not None: span_json['status'] = span.status.format_status_json() if span.same_process_as_parent_span is not None: span_json['sameProcessAsParentSpan'] = \ span.same_process_as_parent_span return span_json
def test_format_attributes_json(self): attrs = { 'key1': 'test string', 'key2': True, 'key3': 100, } attributes = attributes_module.Attributes(attrs) attributes_json = attributes.format_attributes_json() expected_attributes_json = { 'attributeMap': { 'key1': { 'string_value': { 'value': 'test string', 'truncated_byte_count': 0 } }, 'key2': { 'bool_value': True }, 'key3': { 'int_value': 100 } } } self.assertEqual(expected_attributes_json, attributes_json)
def test_set_annotation_with_attributes(self): pb_span = trace_pb2.Span() pb_event = pb_span.time_events.time_event.add() annotation = time_event_module.Annotation( description="hi there", attributes=attributes_module.Attributes( attributes={ 'test_str_key': 'test_str_value', 'test_int_key': 1, 'test_bool_key': False, 'test_double_key': 567.89 })) utils.set_proto_annotation(pb_event.annotation, annotation) self.assertEqual(pb_event.annotation.description.value, "hi there") self.assertEqual(len(pb_event.annotation.attributes.attribute_map), 4) self.assertEqual( pb_event.annotation.attributes.attribute_map['test_str_key'], trace_pb2.AttributeValue(string_value=trace_pb2.TruncatableString( value='test_str_value'))) self.assertEqual( pb_event.annotation.attributes.attribute_map['test_int_key'], trace_pb2.AttributeValue(int_value=1)) self.assertEqual( pb_event.annotation.attributes.attribute_map['test_bool_key'], trace_pb2.AttributeValue(bool_value=False)) self.assertEqual( pb_event.annotation.attributes.attribute_map['test_double_key'], trace_pb2.AttributeValue(double_value=567.89))
def test_set_attribute(self): key = 'test key' value = 'test value' attributes = attributes_module.Attributes() attributes.set_attribute(key=key, value=value) expected_attr = {key: value} self.assertEqual(expected_attr, attributes.attributes)
def test_format_attributes_json_type_error(self): attrs = { 'key1': mock.Mock(), } expected_json = {'attributeMap': {}} attributes = attributes_module.Attributes(attrs) attributes_json = attributes.format_attributes_json() self.assertEqual(attributes_json, expected_json)
def _format_legacy_span_json(span_data): """ :param SpanData span_data: SpanData object to convert :rtype: dict :return: Dictionary representing the Span """ span_json = { 'displayName': utils.get_truncatable_str(span_data.name), 'spanId': span_data.span_id, 'startTime': span_data.start_time, 'endTime': span_data.end_time, 'childSpanCount': span_data.child_span_count, 'kind': span_data.span_kind } if span_data.parent_span_id is not None: span_json['parentSpanId'] = span_data.parent_span_id if span_data.attributes: span_json['attributes'] = attributes.Attributes( span_data.attributes).format_attributes_json() if span_data.stack_trace is not None: span_json['stackTrace'] = \ span_data.stack_trace.format_stack_trace_json() formatted_time_events = [] if span_data.annotations: formatted_time_events.extend({ 'time': aa.timestamp, 'annotation': aa.format_annotation_json() } for aa in span_data.annotations) if span_data.message_events: formatted_time_events.extend( { 'time': aa.timestamp, 'message_event': aa.format_message_event_json() } for aa in span_data.message_events) if formatted_time_events: span_json['timeEvents'] = {'timeEvent': formatted_time_events} if span_data.links: span_json['links'] = { 'link': [link.format_link_json() for link in span_data.links] } if span_data.status is not None: span_json['status'] = span_data.status.format_status_json() if span_data.same_process_as_parent_span is not None: span_json['sameProcessAsParentSpan'] = \ span_data.same_process_as_parent_span return span_json
def add_annotation(self, description, **attrs): """Add an annotation to span. :type description: str :param description: A user-supplied message describing the event. The maximum length for the description is 256 bytes. :type attrs: kwargs :param attrs: keyworded arguments e.g. failed=True, name='Caching' """ at = attributes.Attributes(attrs) self.add_time_event(time_event_module.TimeEvent(datetime.utcnow(), time_event_module.Annotation(description, at)))
def test_set_annotation_without_attributes(self): pb_span = trace_pb2.Span() pb_event0 = pb_span.time_events.time_event.add() pb_event1 = pb_span.time_events.time_event.add() annotation0 = time_event_module.Annotation(description="hi there0") annotation1 = time_event_module.Annotation( description="hi there1", attributes=attributes_module.Attributes()) utils.set_proto_annotation(pb_event0.annotation, annotation0) utils.set_proto_annotation(pb_event1.annotation, annotation1) self.assertEqual(pb_event0.annotation.description.value, "hi there0") self.assertEqual(pb_event1.annotation.description.value, "hi there1") self.assertEqual(len(pb_event0.annotation.attributes.attribute_map), 0) self.assertEqual(len(pb_event1.annotation.attributes.attribute_map), 0)
def test_get_attribute(self): attr = {'key': 'value'} attributes = attributes_module.Attributes(attr) value = attributes.get_attribute('key') self.assertEqual(value, 'value')
def test_delete_attribute(self): attr = {'key1': 'value1', 'key2': 'value2'} attributes = attributes_module.Attributes(attr) attributes.delete_attribute('key1') self.assertEqual(attributes.attributes, {'key2': 'value2'})
def test_constructor_explicit(self): attr = {'key': 'value'} attributes = attributes_module.Attributes(attr) self.assertEqual(attributes.attributes, attr)
def test_constructor_default(self): attributes = attributes_module.Attributes() self.assertEqual(attributes.attributes, {})
def test_translate_to_jaeger(self): self.maxDiff = None trace_id_high = '6e0c63257de34c92' trace_id_low = 'bf9efcd03927272e' trace_id = trace_id_high + trace_id_low span_id = '6e0c63257de34c92' parent_span_id = '1111111111111111' span_attributes = { 'key_bool': False, 'key_string': 'hello_world', 'key_int': 3 } annotation_attributes = { 'annotation_bool': True, 'annotation_string': 'annotation_test', 'key_float': .3 } link_attributes = {'key_bool': True} import datetime s = '2017-08-15T18:02:26.071158' time = datetime.datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%f') time_events = [ time_event.TimeEvent( timestamp=time, annotation=time_event.Annotation( description='First Annotation', attributes=attributes.Attributes(annotation_attributes))), time_event.TimeEvent(timestamp=time, message_event=time_event.MessageEvent( id='message-event-id', uncompressed_size_bytes=0, )), ] time_events2 = [ time_event.TimeEvent(timestamp=time, annotation=time_event.Annotation( description='First Annotation', attributes=None)), time_event.TimeEvent(timestamp=time, message_event=time_event.MessageEvent( id='message-event-id', uncompressed_size_bytes=0, )), ] links = [ link.Link(trace_id=trace_id, span_id=span_id, type=link.Type.CHILD_LINKED_SPAN, attributes=link_attributes), link.Link(trace_id=trace_id, span_id=span_id, type=link.Type.PARENT_LINKED_SPAN, attributes=link_attributes), link.Link(trace_id=trace_id, span_id=span_id, type=link.Type.TYPE_UNSPECIFIED, attributes=link_attributes) ] span_status = status.Status(code=200, message='success') start_time = '2017-08-15T18:02:26.071158Z' end_time = '2017-08-15T18:02:36.071158Z' span_datas = [ span_data.SpanData( name='test1', context=span_context.SpanContext(trace_id=trace_id), span_id=span_id, parent_span_id=parent_span_id, attributes=span_attributes, start_time=start_time, end_time=end_time, child_span_count=0, stack_trace=None, time_events=time_events, links=links, status=span_status, same_process_as_parent_span=None, span_kind=0, ), span_data.SpanData( name='test2', context=None, span_id=span_id, parent_span_id=None, attributes=None, start_time=start_time, end_time=end_time, child_span_count=None, stack_trace=None, time_events=time_events2, links=None, status=None, same_process_as_parent_span=None, span_kind=None, ), span_data.SpanData( name='test3', context=None, span_id=span_id, parent_span_id=None, attributes=None, start_time=start_time, end_time=end_time, child_span_count=None, stack_trace=None, time_events=None, links=None, status=None, same_process_as_parent_span=None, span_kind=None, ) ] exporter = jaeger_exporter.JaegerExporter() spans = exporter.translate_to_jaeger(span_datas) expected_spans = [ jaeger.Span( traceIdHigh=7929822056569588882, traceIdLow=-4638992594902767826, spanId=7929822056569588882, parentSpanId=1229782938247303441, operationName='test1', startTime=1502820146071158, duration=10000000, flags=1, tags=[ jaeger.Tag(key='key_bool', vType=jaeger.TagType.BOOL, vBool=False), jaeger.Tag(key='key_string', vType=jaeger.TagType.STRING, vStr='hello_world'), jaeger.Tag(key='key_int', vType=jaeger.TagType.LONG, vLong=3), jaeger.Tag(key='status.code', vType=jaeger.TagType.LONG, vLong=200), jaeger.Tag(key='status.message', vType=jaeger.TagType.STRING, vStr='success') ], references=[ jaeger.SpanRef(refType=jaeger.SpanRefType.CHILD_OF, traceIdHigh=7929822056569588882, traceIdLow=-4638992594902767826, spanId=7929822056569588882), jaeger.SpanRef(refType=jaeger.SpanRefType.FOLLOWS_FROM, traceIdHigh=7929822056569588882, traceIdLow=-4638992594902767826, spanId=7929822056569588882), jaeger.SpanRef(refType=None, traceIdHigh=7929822056569588882, traceIdLow=-4638992594902767826, spanId=7929822056569588882) ], logs=[ jaeger.Log(timestamp=1502820146071158, fields=[ jaeger.Tag(key='annotation_bool', vType=jaeger.TagType.BOOL, vBool=True), jaeger.Tag(key='annotation_string', vType=jaeger.TagType.STRING, vStr='annotation_test'), jaeger.Tag(key='message', vType=jaeger.TagType.STRING, vStr='First Annotation') ]) ]), jaeger.Span(operationName="test2", traceIdHigh=7929822056569588882, traceIdLow=-4638992594902767826, spanId=7929822056569588882, parentSpanId=0, startTime=1502820146071158, duration=10000000, logs=[ jaeger.Log(timestamp=1502820146071158, fields=[ jaeger.Tag( key='message', vType=jaeger.TagType.STRING, vStr='First Annotation') ]) ]), jaeger.Span(operationName="test3", traceIdHigh=7929822056569588882, traceIdLow=-4638992594902767826, spanId=7929822056569588882, parentSpanId=0, startTime=1502820146071158, duration=10000000, logs=[]) ] spans_json = [span.format_span_json() for span in spans] expected_spans_json = [ span.format_span_json() for span in expected_spans ] span = spans_json[0] expected_span = expected_spans_json[0] try: listsEqual = self.assertCountEqual except AttributeError: listsEqual = self.assertItemsEqual log = span.get('logs')[0] expected_log = expected_span.get('logs')[0] self.assertEqual(log.get('timestamp'), expected_log.get('timestamp')) listsEqual(log.get('fields'), expected_log.get('fields')) listsEqual(span.get('tags'), expected_span.get('tags')) listsEqual(span.get('references'), expected_span.get('references')) self.assertEqual(span.get('traceIdHigh'), expected_span.get('traceIdHigh')) self.assertEqual(span.get('traceIdLow'), expected_span.get('traceIdLow')) self.assertEqual(span.get('spanId'), expected_span.get('spanId')) self.assertEqual(span.get('parentSpanId'), expected_span.get('parentSpanId')) self.assertEqual(span.get('operationName'), expected_span.get('operationName')) self.assertEqual(span.get('startTime'), expected_span.get('startTime')) self.assertEqual(span.get('duration'), expected_span.get('duration')) self.assertEqual(span.get('flags'), expected_span.get('flags')) self.assertEqual(spans_json[1], expected_spans_json[1]) self.assertEqual(spans_json[2], expected_spans_json[2])
def test_translate_time_events(self): annotation0_ts = datetime.utcnow() + timedelta(seconds=-10) annotation1_ts = datetime.utcnow() + timedelta(seconds=-9) message0_ts = datetime.utcnow() + timedelta(seconds=-8) message1_ts = datetime.utcnow() + timedelta(seconds=-7) message2_ts = datetime.utcnow() + timedelta(seconds=-6) span_data = span_data_module.SpanData( context=span_context_module.SpanContext( trace_id='6e0c63257de34c92bf9efcd03927272e'), span_id='6e0c63257de34c92', time_events=[ time_event_module.TimeEvent( timestamp=annotation0_ts, annotation=time_event_module.Annotation( description="hi there0", attributes=attributes_module.Attributes( attributes={ 'test_str_key': 'test_str_value', 'test_int_key': 1, 'test_bool_key': False, 'test_double_key': 567.89 }))), time_event_module.TimeEvent( timestamp=annotation1_ts, annotation=time_event_module.Annotation( description="hi there1")), time_event_module.TimeEvent( timestamp=message0_ts, message_event=time_event_module.MessageEvent( id=0, type=time_event_module.Type.SENT, uncompressed_size_bytes=10, compressed_size_bytes=1)), time_event_module.TimeEvent( timestamp=message1_ts, message_event=time_event_module.MessageEvent( id=1, type=time_event_module.Type.RECEIVED, uncompressed_size_bytes=20, compressed_size_bytes=2)), time_event_module.TimeEvent( timestamp=message2_ts, message_event=time_event_module.MessageEvent( id=2, type=time_event_module.Type.TYPE_UNSPECIFIED, uncompressed_size_bytes=30, compressed_size_bytes=3)) ], span_kind=span_module.SpanKind.SERVER, status=None, start_time=None, end_time=None, child_span_count=None, name=None, parent_span_id=None, attributes=None, same_process_as_parent_span=False, stack_trace=None, links=None) pb_span = utils.translate_to_trace_proto(span_data) self.assertEqual(len(pb_span.time_events.time_event), 5) event0 = pb_span.time_events.time_event[0] event1 = pb_span.time_events.time_event[1] event2 = pb_span.time_events.time_event[2] event3 = pb_span.time_events.time_event[3] event4 = pb_span.time_events.time_event[4] self.assertEqual(event0.time.ToDatetime(), annotation0_ts) self.assertEqual(event1.time.ToDatetime(), annotation1_ts) self.assertEqual(event2.time.ToDatetime(), message0_ts) self.assertEqual(event3.time.ToDatetime(), message1_ts) self.assertEqual(event4.time.ToDatetime(), message2_ts) self.assertEqual(event0.annotation.description.value, "hi there0") self.assertEqual(event1.annotation.description.value, "hi there1") self.assertEqual(len(event0.annotation.attributes.attribute_map), 4) self.assertEqual(len(event1.annotation.attributes.attribute_map), 0) self.assertEqual( event0.annotation.attributes.attribute_map['test_str_key'], trace_pb2.AttributeValue(string_value=trace_pb2.TruncatableString( value='test_str_value'))) self.assertEqual( event0.annotation.attributes.attribute_map['test_int_key'], trace_pb2.AttributeValue(int_value=1)) self.assertEqual( event0.annotation.attributes.attribute_map['test_bool_key'], trace_pb2.AttributeValue(bool_value=False)) self.assertEqual( event0.annotation.attributes.attribute_map['test_double_key'], trace_pb2.AttributeValue(double_value=567.89)) self.assertEqual(event2.message_event.id, 0) self.assertEqual(event3.message_event.id, 1) self.assertEqual(event4.message_event.id, 2) self.assertEqual(event2.message_event.uncompressed_size, 10) self.assertEqual(event3.message_event.uncompressed_size, 20) self.assertEqual(event4.message_event.uncompressed_size, 30) self.assertEqual(event2.message_event.compressed_size, 1) self.assertEqual(event3.message_event.compressed_size, 2) self.assertEqual(event4.message_event.compressed_size, 3) self.assertEqual(event2.message_event.type, 1) self.assertEqual(event3.message_event.type, 2) self.assertEqual(event4.message_event.type, 0)
def test_translate_links(self): hex_encoder = codecs.getencoder('hex') span_data = span_data_module.SpanData( context=span_context_module.SpanContext( trace_id='6e0c63257de34c92bf9efcd03927272e'), span_id='6e0c63257de34c92', links=[ link_module.Link(trace_id='0e0c63257de34c92bf9efcd03927272e', span_id='0e0c63257de34c92', type=link_module.Type.TYPE_UNSPECIFIED, attributes=attributes_module.Attributes( attributes={ 'test_str_key': 'test_str_value', 'test_int_key': 1, 'test_bool_key': False, 'test_double_key': 567.89 })), link_module.Link(trace_id='1e0c63257de34c92bf9efcd03927272e', span_id='1e0c63257de34c92', type=link_module.Type.CHILD_LINKED_SPAN), link_module.Link(trace_id='2e0c63257de34c92bf9efcd03927272e', span_id='2e0c63257de34c92', type=link_module.Type.PARENT_LINKED_SPAN) ], span_kind=span_module.SpanKind.SERVER, status=None, start_time=None, end_time=None, child_span_count=None, name=None, parent_span_id=None, attributes=None, same_process_as_parent_span=False, stack_trace=None, time_events=None) pb_span = utils.translate_to_trace_proto(span_data) self.assertEqual(len(pb_span.links.link), 3) self.assertEqual( hex_encoder(pb_span.links.link[0].trace_id)[0], b'0e0c63257de34c92bf9efcd03927272e') self.assertEqual( hex_encoder(pb_span.links.link[1].trace_id)[0], b'1e0c63257de34c92bf9efcd03927272e') self.assertEqual( hex_encoder(pb_span.links.link[2].trace_id)[0], b'2e0c63257de34c92bf9efcd03927272e') self.assertEqual( hex_encoder(pb_span.links.link[0].span_id)[0], b'0e0c63257de34c92') self.assertEqual( hex_encoder(pb_span.links.link[1].span_id)[0], b'1e0c63257de34c92') self.assertEqual( hex_encoder(pb_span.links.link[2].span_id)[0], b'2e0c63257de34c92') self.assertEqual(pb_span.links.link[0].type, 0) self.assertEqual(pb_span.links.link[1].type, 1) self.assertEqual(pb_span.links.link[2].type, 2) self.assertEqual(len(pb_span.links.link[0].attributes.attribute_map), 4) self.assertEqual(len(pb_span.links.link[1].attributes.attribute_map), 0) self.assertEqual(len(pb_span.links.link[2].attributes.attribute_map), 0) self.assertEqual( pb_span.links.link[0].attributes.attribute_map['test_str_key'], trace_pb2.AttributeValue(string_value=trace_pb2.TruncatableString( value='test_str_value'))) self.assertEqual( pb_span.links.link[0].attributes.attribute_map['test_int_key'], trace_pb2.AttributeValue(int_value=1)) self.assertEqual( pb_span.links.link[0].attributes.attribute_map['test_bool_key'], trace_pb2.AttributeValue(bool_value=False)) self.assertEqual( pb_span.links.link[0].attributes.attribute_map['test_double_key'], trace_pb2.AttributeValue(double_value=567.89))