def _test_encode_max_tag_length(self, max_tag_value_length: int): otel_span, expected_tag_output = self.get_data_for_max_tag_length_test( max_tag_value_length) service_name = otel_span.name expected_output = zipkin_pb2.ListOfSpans(spans=[ zipkin_pb2.Span( trace_id=ProtobufEncoder._encode_trace_id( otel_span.context.trace_id), id=ProtobufEncoder._encode_span_id(otel_span.context.span_id), name=service_name, timestamp=ProtobufEncoder._nsec_to_usec_round( otel_span.start_time), duration=ProtobufEncoder._nsec_to_usec_round( otel_span.end_time - otel_span.start_time), local_endpoint=zipkin_pb2.Endpoint(service_name=service_name), kind=ProtobufEncoder.SPAN_KIND_MAP[SpanKind.INTERNAL], tags=expected_tag_output, annotations=None, debug=True, ) ]) actual_output = zipkin_pb2.ListOfSpans.FromString( ProtobufEncoder(max_tag_value_length).serialize([otel_span], NodeEndpoint())) self.assertEqual(actual_output, expected_output)
def __init__( self, protocol: Protocol, endpoint: Optional[str] = None, local_node_ipv4: IpInput = None, local_node_ipv6: IpInput = None, local_node_port: Optional[int] = None, max_tag_value_length: Optional[int] = None, ): self.local_node = NodeEndpoint( local_node_ipv4, local_node_ipv6, local_node_port ) if endpoint is None: endpoint = ( environ.get(OTEL_EXPORTER_ZIPKIN_ENDPOINT) or DEFAULT_ENDPOINT ) self.endpoint = endpoint if protocol == Protocol.V1_JSON: self.encoder = JsonV1Encoder(max_tag_value_length) elif protocol == Protocol.V2_JSON: self.encoder = JsonV2Encoder(max_tag_value_length) elif protocol == Protocol.V2_PROTOBUF: self.encoder = ProtobufEncoder(max_tag_value_length)
def _test_encode_max_tag_length(self, max_tag_value_length: int): otel_span, expected_tag_output = self.get_data_for_max_tag_length_test( max_tag_value_length) service_name = otel_span.name expected_output = [{ "traceId": JsonV2Encoder._encode_trace_id(otel_span.context.trace_id), "id": JsonV2Encoder._encode_span_id(otel_span.context.span_id), "name": service_name, "timestamp": JsonV2Encoder._nsec_to_usec_round(otel_span.start_time), "duration": JsonV2Encoder._nsec_to_usec_round(otel_span.end_time - otel_span.start_time), "localEndpoint": { "serviceName": service_name }, "kind": JsonV2Encoder.SPAN_KIND_MAP[SpanKind.INTERNAL], "tags": expected_tag_output, "debug": True, }] self.assert_equal_encoded_spans( json.dumps(expected_output), JsonV2Encoder(max_tag_value_length).serialize([otel_span], NodeEndpoint()), )
def test_encode_local_endpoint_default(self): self.assertEqual( self.get_encoder_default()._encode_local_endpoint( NodeEndpoint() ), {"serviceName": TEST_SERVICE_NAME}, )
def test_constructor_explicits(self): ipv4 = "192.168.0.1" ipv6 = "2001:db8::c001" port = 414120 node_endpoint = NodeEndpoint(ipv4, ipv6, port) self.assertEqual(node_endpoint.ipv4, ipaddress.IPv4Address(ipv4)) self.assertEqual(node_endpoint.ipv6, ipaddress.IPv6Address(ipv6)) self.assertEqual(node_endpoint.port, port) self.assertEqual(node_endpoint.service_name, TEST_SERVICE_NAME)
def test_encode_local_endpoint_explicits(self): ipv4 = "192.168.0.1" ipv6 = "2001:db8::c001" port = 414120 self.assertEqual( ProtobufEncoder()._encode_local_endpoint( NodeEndpoint(ipv4, ipv6, port)), zipkin_pb2.Endpoint( service_name=TEST_SERVICE_NAME, ipv4=ipaddress.ip_address(ipv4).packed, ipv6=ipaddress.ip_address(ipv6).packed, port=port, ), )
def test_encode_local_endpoint_explicits(self): ipv4 = "192.168.0.1" ipv6 = "2001:db8::c001" port = 414120 self.assertEqual( self.get_encoder_default()._encode_local_endpoint( NodeEndpoint(ipv4, ipv6, port)), { "serviceName": TEST_SERVICE_NAME, "ipv4": ipv4, "ipv6": ipv6, "port": port, }, )
def test_encode_id_zero_padding(self): trace_id = 0x0E0C63257DE34C926F9EFCD03927272E span_id = 0x04BF92DEEFC58C92 parent_id = 0x0AAAAAAAAAAAAAAA start_time = 683647322 * 10**9 # in ns duration = 50 * 10**6 end_time = start_time + duration otel_span = trace._Span( name=TEST_SERVICE_NAME, context=trace_api.SpanContext( trace_id, span_id, is_remote=False, trace_flags=TraceFlags(TraceFlags.SAMPLED), ), parent=trace_api.SpanContext(trace_id, parent_id, is_remote=False), resource=trace.Resource({}), ) otel_span.start(start_time=start_time) otel_span.end(end_time=end_time) expected_output = [{ "traceId": format(trace_id, "032x"), "id": format(span_id, "016x"), "name": TEST_SERVICE_NAME, "timestamp": JsonV2Encoder._nsec_to_usec_round(start_time), "duration": JsonV2Encoder._nsec_to_usec_round(duration), "localEndpoint": { "serviceName": TEST_SERVICE_NAME }, "kind": JsonV2Encoder.SPAN_KIND_MAP[SpanKind.INTERNAL], "debug": True, "parentId": format(parent_id, "016x"), }] self.assert_equal_encoded_spans( json.dumps(expected_output), JsonV2Encoder().serialize([otel_span], NodeEndpoint()), )
def __init__( self, version: Protocol = Protocol.V2, endpoint: Optional[str] = None, local_node_ipv4: IpInput = None, local_node_ipv6: IpInput = None, local_node_port: Optional[int] = None, max_tag_value_length: Optional[int] = None, timeout: Optional[int] = None, ): """Zipkin exporter. Args: version: The protocol version to be used. endpoint: The endpoint of the Zipkin collector. local_node_ipv4: Primary IPv4 address associated with this connection. local_node_ipv6: Primary IPv6 address associated with this connection. local_node_port: Depending on context, this could be a listen port or the client-side of a socket. max_tag_value_length: Max length string attribute values can have. timeout: Maximum time the Zipkin exporter will wait for each batch export. The default value is 10s. The tuple (local_node_ipv4, local_node_ipv6, local_node_port) is used to represent the network context of a node in the service graph. """ self.local_node = NodeEndpoint(local_node_ipv4, local_node_ipv6, local_node_port) if endpoint is None: endpoint = (environ.get(OTEL_EXPORTER_ZIPKIN_ENDPOINT) or DEFAULT_ENDPOINT) self.endpoint = endpoint if version == Protocol.V1: self.encoder = JsonV1Encoder(max_tag_value_length) elif version == Protocol.V2: self.encoder = JsonV2Encoder(max_tag_value_length) self.session = requests.Session() self.session.headers.update( {"Content-Type": self.encoder.content_type()}) self._closed = False self.timeout = timeout or int( environ.get(OTEL_EXPORTER_ZIPKIN_TIMEOUT, 10))
def __init__( self, endpoint: Optional[str] = None, local_node_ipv4: IpInput = None, local_node_ipv6: IpInput = None, local_node_port: Optional[int] = None, max_tag_value_length: Optional[int] = None, ): self.local_node = NodeEndpoint( local_node_ipv4, local_node_ipv6, local_node_port ) if endpoint is None: endpoint = ( environ.get(OTEL_EXPORTER_ZIPKIN_ENDPOINT) or DEFAULT_ENDPOINT ) self.endpoint = endpoint self.encoder = ProtobufEncoder(max_tag_value_length)
def _test_encode_max_tag_length(self, max_tag_value_length: int): otel_span, expected_tag_output = self.get_data_for_max_tag_length_test( max_tag_value_length ) service_name = otel_span.name binary_annotations = [] for tag_key, tag_expected_value in expected_tag_output.items(): binary_annotations.append( { "key": tag_key, "value": tag_expected_value, "endpoint": {"serviceName": service_name}, } ) expected_output = [ { "traceId": JsonV1Encoder._encode_trace_id( otel_span.context.trace_id ), "id": JsonV1Encoder._encode_span_id(otel_span.context.span_id), "name": service_name, "timestamp": JsonV1Encoder._nsec_to_usec_round( otel_span.start_time ), "duration": JsonV1Encoder._nsec_to_usec_round( otel_span.end_time - otel_span.start_time ), "binaryAnnotations": binary_annotations, "debug": True, } ] self.assert_equal_encoded_spans( json.dumps(expected_output), JsonV1Encoder(max_tag_value_length).serialize( [otel_span], NodeEndpoint() ), )
def test_ipv6_invalid_raises_error(self): with self.assertRaises(ValueError): NodeEndpoint(ipv6="invalid-ipv6-address")
def test_encode(self): local_endpoint = {"serviceName": TEST_SERVICE_NAME} span_kind = JsonV2Encoder.SPAN_KIND_MAP[SpanKind.INTERNAL] otel_spans = self.get_exhaustive_otel_span_list() trace_id = JsonV2Encoder._encode_trace_id( otel_spans[0].context.trace_id) expected_output = [ { "traceId": trace_id, "id": JsonV2Encoder._encode_span_id(otel_spans[0].context.span_id), "name": otel_spans[0].name, "timestamp": otel_spans[0].start_time // 10**3, "duration": (otel_spans[0].end_time // 10**3) - (otel_spans[0].start_time // 10**3), "localEndpoint": local_endpoint, "kind": span_kind, "tags": { "key_bool": "false", "key_string": "hello_world", "key_float": "111.22", "otel.status_code": "OK", }, "annotations": [{ "timestamp": otel_spans[0].events[0].timestamp // 10**3, "value": json.dumps( { "event0": { "annotation_bool": True, "annotation_string": "annotation_test", "key_float": 0.3, } }, sort_keys=True, ), }], "debug": True, "parentId": JsonV2Encoder._encode_span_id(otel_spans[0].parent.span_id), }, { "traceId": trace_id, "id": JsonV2Encoder._encode_span_id(otel_spans[1].context.span_id), "name": otel_spans[1].name, "timestamp": otel_spans[1].start_time // 10**3, "duration": (otel_spans[1].end_time // 10**3) - (otel_spans[1].start_time // 10**3), "localEndpoint": local_endpoint, "kind": span_kind, "tags": { "key_resource": "some_resource", "otel.status_code": "ERROR", "error": "Example description", }, }, { "traceId": trace_id, "id": JsonV2Encoder._encode_span_id(otel_spans[2].context.span_id), "name": otel_spans[2].name, "timestamp": otel_spans[2].start_time // 10**3, "duration": (otel_spans[2].end_time // 10**3) - (otel_spans[2].start_time // 10**3), "localEndpoint": local_endpoint, "kind": span_kind, "tags": { "key_string": "hello_world", "key_resource": "some_resource", }, }, { "traceId": trace_id, "id": JsonV2Encoder._encode_span_id(otel_spans[3].context.span_id), "name": otel_spans[3].name, "timestamp": otel_spans[3].start_time // 10**3, "duration": (otel_spans[3].end_time // 10**3) - (otel_spans[3].start_time // 10**3), "localEndpoint": local_endpoint, "kind": span_kind, "tags": { NAME_KEY: "name", VERSION_KEY: "version" }, }, ] self.assert_equal_encoded_spans( json.dumps(expected_output), JsonV2Encoder().serialize(otel_spans, NodeEndpoint()), )
def test_encode_local_endpoint_default(self): self.assertEqual( ProtobufEncoder()._encode_local_endpoint(NodeEndpoint()), zipkin_pb2.Endpoint(service_name=TEST_SERVICE_NAME), )
def test_encode(self): local_endpoint = zipkin_pb2.Endpoint(service_name=TEST_SERVICE_NAME) span_kind = ProtobufEncoder.SPAN_KIND_MAP[SpanKind.INTERNAL] otel_spans = self.get_exhaustive_otel_span_list() trace_id = ProtobufEncoder._encode_trace_id( otel_spans[0].context.trace_id ) expected_output = zipkin_pb2.ListOfSpans( spans=[ zipkin_pb2.Span( trace_id=trace_id, id=ProtobufEncoder._encode_span_id( otel_spans[0].context.span_id ), name=otel_spans[0].name, timestamp=ProtobufEncoder._nsec_to_usec_round( otel_spans[0].start_time ), duration=( ProtobufEncoder._nsec_to_usec_round( otel_spans[0].end_time - otel_spans[0].start_time ) ), local_endpoint=local_endpoint, kind=span_kind, tags={ "key_bool": "false", "key_string": "hello_world", "key_float": "111.22", "otel.status_code": "OK", }, debug=True, parent_id=ProtobufEncoder._encode_span_id( otel_spans[0].parent.span_id ), annotations=[ zipkin_pb2.Annotation( timestamp=ProtobufEncoder._nsec_to_usec_round( otel_spans[0].events[0].timestamp ), value=json.dumps( { "event0": { "annotation_bool": True, "annotation_string": "annotation_test", "key_float": 0.3, } }, sort_keys=True, ), ), ], ), zipkin_pb2.Span( trace_id=trace_id, id=ProtobufEncoder._encode_span_id( otel_spans[1].context.span_id ), name=otel_spans[1].name, timestamp=ProtobufEncoder._nsec_to_usec_round( otel_spans[1].start_time ), duration=( ProtobufEncoder._nsec_to_usec_round( otel_spans[1].end_time - otel_spans[1].start_time ) ), local_endpoint=local_endpoint, kind=span_kind, tags={ "key_resource": "some_resource", "otel.status_code": "ERROR", "error": "Example description", }, debug=False, ), zipkin_pb2.Span( trace_id=trace_id, id=ProtobufEncoder._encode_span_id( otel_spans[2].context.span_id ), name=otel_spans[2].name, timestamp=ProtobufEncoder._nsec_to_usec_round( otel_spans[2].start_time ), duration=( ProtobufEncoder._nsec_to_usec_round( otel_spans[2].end_time - otel_spans[2].start_time ) ), local_endpoint=local_endpoint, kind=span_kind, tags={ "key_string": "hello_world", "key_resource": "some_resource", }, debug=False, ), zipkin_pb2.Span( trace_id=trace_id, id=ProtobufEncoder._encode_span_id( otel_spans[3].context.span_id ), name=otel_spans[3].name, timestamp=ProtobufEncoder._nsec_to_usec_round( otel_spans[3].start_time ), duration=( ProtobufEncoder._nsec_to_usec_round( otel_spans[3].end_time - otel_spans[3].start_time ) ), local_endpoint=local_endpoint, kind=span_kind, tags={NAME_KEY: "name", VERSION_KEY: "version"}, debug=False, ), ], ) actual_output = zipkin_pb2.ListOfSpans.FromString( ProtobufEncoder().serialize(otel_spans, NodeEndpoint()) ) self.assertEqual(actual_output, expected_output)
def test_ipv6_passed_ipv4_raises_error(self): with self.assertRaises(ValueError): NodeEndpoint(ipv6="192.168.0.1")
def test_ipv4_passed_ipv6_raises_error(self): with self.assertRaises(ValueError): NodeEndpoint(ipv4="2001:db8::c001")
def test_constructor_default(self): node_endpoint = NodeEndpoint() self.assertEqual(node_endpoint.ipv4, None) self.assertEqual(node_endpoint.ipv6, None) self.assertEqual(node_endpoint.port, None) self.assertEqual(node_endpoint.service_name, TEST_SERVICE_NAME)