Пример #1
0
    def zipkin_span_params(self, span):
        span_params = self.log_span_params(span)

        timing = {'ss': span.start_time, 'sr': span.start_time + span.duration}
        annotations = annotation_list_builder(timing, self.endpoint)
        zipkin_attrs = ZipkinAttrs(
            trace_id=span_params['trace_id'],
            span_id=span_params['span_id'],
            parent_span_id=span_params['parent_span_id'],
            flags=span_params['flags'],
            is_sampled=span_params['is_sampled'])

        return {
            **span_params,
            'zipkin_attrs':
            zipkin_attrs,
            'annotations':
            annotations,
            'binary_annotations':
            binary_annotation_list_builder(
                {
                    **span.context.baggage,
                    **span.tags
                }, self.endpoint),
        }
Пример #2
0
    def encode_span(self, span_builder):
        """Encodes the current span to thrift."""
        span = span_builder.build_v1_span()

        thrift_endpoint = thrift.create_endpoint(
            span.endpoint.port,
            span.endpoint.service_name,
            span.endpoint.ipv4,
            span.endpoint.ipv6,
        )

        thrift_annotations = thrift.annotation_list_builder(
            span.annotations,
            thrift_endpoint,
        )

        thrift_binary_annotations = thrift.binary_annotation_list_builder(
            span.binary_annotations,
            thrift_endpoint,
        )

        # Add sa binary annotation
        if span.sa_endpoint is not None:
            thrift_sa_endpoint = thrift.create_endpoint(
                span.sa_endpoint.port,
                span.sa_endpoint.service_name,
                span.sa_endpoint.ipv4,
                span.sa_endpoint.ipv6,
            )
            thrift_binary_annotations.append(thrift.create_binary_annotation(
                key=thrift.zipkin_core.SERVER_ADDR,
                value=thrift.SERVER_ADDR_VAL,
                annotation_type=thrift.zipkin_core.AnnotationType.BOOL,
                host=thrift_sa_endpoint,
            ))

        thrift_span = thrift.create_span(
            span.id,
            span.parent_id,
            span.trace_id,
            span.name,
            thrift_annotations,
            thrift_binary_annotations,
            span.timestamp,
            span.duration,
        )

        encoded_span = thrift.span_to_bytes(thrift_span)
        return encoded_span
Пример #3
0
    def test__decode_thrift_annotations_server_span(self, thrift_endpoint):
        timestamp = 1.0
        decoder = _V1ThriftDecoder()
        thrift_annotations = thrift.annotation_list_builder(
            {"sr": timestamp, "ss": timestamp + 10}, thrift_endpoint,
        )

        annotations, end, kind, ts, dur = decoder._decode_thrift_annotations(
            thrift_annotations,
        )
        assert annotations == {}
        assert end == Endpoint("test_service", "10.0.0.1", None, 8888)
        assert kind == Kind.SERVER
        assert ts == timestamp * USEC
        assert dur == 10 * USEC
Пример #4
0
    def test__decode_thrift_annotations(self, thrift_endpoint):
        timestamp = 1.0
        decoder = _V1ThriftDecoder()
        thrift_annotations = thrift.annotation_list_builder(
            {"cs": timestamp, "cr": timestamp + 10, "my_annotation": timestamp + 15},
            thrift_endpoint,
        )

        annotations, end, kind, ts, dur = decoder._decode_thrift_annotations(
            thrift_annotations,
        )
        assert annotations == {"my_annotation": 16.0}
        assert end == Endpoint("test_service", "10.0.0.1", None, 8888)
        assert kind == Kind.CLIENT
        assert ts == timestamp * USEC
        assert dur == 10 * USEC
Пример #5
0
    def test__decode_thrift_annotations(self, thrift_endpoint):
        timestamp = 1.0
        decoder = _V1ThriftDecoder()
        thrift_annotations = thrift.annotation_list_builder(
            {
                'cs': timestamp,
                'cr': timestamp + 10,
                'my_annotation': timestamp + 15,
            },
            thrift_endpoint,
        )

        annotations, end, kind, ts, dur = decoder._decode_thrift_annotations(
            thrift_annotations, )
        assert annotations == {'my_annotation': 16.0}
        assert end == Endpoint('test_service', '10.0.0.1', None, 8888)
        assert kind == Kind.CLIENT
        assert ts == timestamp * USEC
        assert dur == 10 * USEC
Пример #6
0
    def encode_span(self, v2_span):
        """Encodes the current span to thrift."""
        span = v2_span.build_v1_span()

        thrift_endpoint = thrift.create_endpoint(
            span.endpoint.port,
            span.endpoint.service_name,
            span.endpoint.ipv4,
            span.endpoint.ipv6,
        )

        thrift_annotations = thrift.annotation_list_builder(
            span.annotations,
            thrift_endpoint,
        )

        thrift_binary_annotations = thrift.binary_annotation_list_builder(
            span.binary_annotations,
            thrift_endpoint,
        )

        # Add sa/ca binary annotations
        if v2_span.remote_endpoint:
            self.encode_remote_endpoint(
                v2_span.remote_endpoint,
                v2_span.kind,
                thrift_binary_annotations,
            )

        thrift_span = thrift.create_span(
            span.id,
            span.parent_id,
            span.trace_id,
            span.name,
            thrift_annotations,
            thrift_binary_annotations,
            span.timestamp,
            span.duration,
        )

        encoded_span = thrift.span_to_bytes(thrift_span)
        return encoded_span
Пример #7
0
    def test__decode_thrift_annotations_local_span(self, thrift_endpoint):
        timestamp = 1.0
        decoder = _V1ThriftDecoder()
        thrift_annotations = thrift.annotation_list_builder(
            {
                'cs': timestamp,
                'sr': timestamp,
                'ss': timestamp + 10,
                'cr': timestamp + 10,
            },
            thrift_endpoint,
        )

        annotations, end, kind, ts, dur = decoder._decode_thrift_annotations(
            thrift_annotations, )
        assert annotations == {}
        assert end == Endpoint('test_service', '10.0.0.1', None, 8888)
        assert kind == Kind.LOCAL
        # ts and dur are not computed for a local span since those always have
        # timestamp and duration set as span arguments.
        assert ts is None
        assert dur is None
Пример #8
0
    def log_spans(self):
        """Main function to log all the annotations stored during the entire
        request. This is done if the request is sampled and the response was
        a success. It also logs the service `ss` and `sr` annotations.
        """
        if self.zipkin_attrs.is_sampled:
            # Collect additional annotations from the logging handler
            annotations_by_span_id = defaultdict(dict)
            binary_annotations_by_span_id = defaultdict(dict)
            for msg in self.log_handler.extra_annotations:
                span_id = msg['parent_span_id'] or self.zipkin_attrs.span_id
                # This should check if these are non-None
                annotations_by_span_id[span_id].update(msg['annotations'])
                binary_annotations_by_span_id[span_id].update(
                    msg['binary_annotations'])

            # Collect, annotate, and log client spans from the logging handler
            for span in self.log_handler.client_spans:
                # The parent_span_id is either the parent ID set in the
                # logging handler or the current Zipkin context's span ID.
                parent_span_id = (span['parent_span_id']
                                  or self.zipkin_attrs.span_id)
                # A new client span's span ID can be overridden
                span_id = span['span_id'] or generate_random_64bit_string()
                endpoint = copy_endpoint_with_new_service_name(
                    self.thrift_endpoint, span['service_name'])
                # Collect annotations both logged with the new spans and
                # logged in separate log messages.
                annotations = span['annotations']
                annotations.update(annotations_by_span_id[span_id])
                binary_annotations = span['binary_annotations']
                binary_annotations.update(
                    binary_annotations_by_span_id[span_id])
                # Create serializable thrift objects of annotations
                thrift_annotations = annotation_list_builder(
                    annotations, endpoint)
                thrift_binary_annotations = binary_annotation_list_builder(
                    binary_annotations, endpoint)

                print("logging_helper:1")
                log_span(
                    span_id=span_id,
                    parent_span_id=parent_span_id,
                    trace_id=self.zipkin_attrs.trace_id,
                    span_name=span['span_name'],
                    annotations=thrift_annotations,
                    binary_annotations=thrift_binary_annotations,
                    transport_handler=self.transport_handler,
                )

            # Collect extra annotations for server span, then log it.
            extra_annotations = annotations_by_span_id[
                self.zipkin_attrs.span_id]
            extra_binary_annotations = binary_annotations_by_span_id[
                self.zipkin_attrs.span_id]
            annotations = dict(sr=self.start_timestamp,
                               ss=self.end_timestamp,
                               **extra_annotations)
            """ FIXME sunyan: disable it!
            if self.add_logging_annotation:
                annotations[LOGGING_START_KEY] = logging_start
            """

            thrift_annotations = annotation_list_builder(
                annotations,
                self.thrift_endpoint,
            )

            # Binary annotations can be set through debug messages or the
            # set_extra_binary_annotations registry setting.
            self.binary_annotations_dict.update(extra_binary_annotations)
            thrift_binary_annotations = binary_annotation_list_builder(
                self.binary_annotations_dict,
                self.thrift_endpoint,
            )

            print("logging_helper:2")
            log_span(
                span_id=self.zipkin_attrs.span_id,
                parent_span_id=self.zipkin_attrs.parent_span_id,
                trace_id=self.zipkin_attrs.trace_id,
                span_name=self.span_name,
                annotations=thrift_annotations,
                binary_annotations=thrift_binary_annotations,
                transport_handler=self.transport_handler,
            )
Пример #9
0
def check_v1_thrift(obj, zipkin_attrs, inner_span_id, ts):
    inner_span, root_span = _decode_binary_thrift_objs(obj)

    endpoint = thrift.create_endpoint(
        port=8080,
        service_name='test_service_name',
        ipv4='10.0.0.0',
    )
    binary_annotations = thrift.binary_annotation_list_builder(
        {'some_key': 'some_value'},
        endpoint,
    )
    binary_annotations.append(thrift.create_binary_annotation(
        'sa',
        '\x01',
        zipkin_core.AnnotationType.BOOL,
        thrift.create_endpoint(
            port=8888,
            service_name='sa_service',
            ipv6='2001:0db8:85a3:0000:0000:8a2e:0370:7334',
        ),
    ))

    expected_root = thrift.create_span(
        span_id=zipkin_attrs.span_id,
        parent_span_id=zipkin_attrs.parent_span_id,
        trace_id=zipkin_attrs.trace_id,
        span_name='test_span_name',
        annotations=thrift.annotation_list_builder(
            OrderedDict([('cs', ts), ('cr', ts + 10)]),
            endpoint,
        ),
        binary_annotations=binary_annotations,
        timestamp_s=None,
        duration_s=None,
    )
    # py.test diffs of thrift Spans are pretty useless and hide many things
    # These prints would only appear on stdout if the test fails and help comparing
    # the 2 spans.
    print(root_span)
    print(expected_root)
    assert root_span == expected_root

    expected_inner = thrift.create_span(
        span_id=inner_span_id,
        parent_span_id=zipkin_attrs.span_id,
        trace_id=zipkin_attrs.trace_id,
        span_name='inner_span',
        annotations=thrift.annotation_list_builder(
            OrderedDict([('cs', ts), ('sr', ts), ('ss', ts + 5),
                         ('cr', ts + 5), ('ws', ts)]),
            endpoint,
        ),
        binary_annotations=[],
        timestamp_s=ts,
        duration_s=5,
    )
    # py.test diffs of thrift Spans are pretty useless and hide many things
    # These prints would only appear on stdout if the test fails and help comparing
    # the 2 spans.
    print(inner_span)
    print(expected_inner)
    assert inner_span == expected_inner
Пример #10
0
    def log_spans(self):
        """Main function to log all the annotations stored during the entire
        request. This is done if the request is sampled and the response was
        a success. It also logs the service (`ss` and `sr`) or the client
        ('cs' and 'cr') annotations.
        """
        if self.zipkin_attrs.is_sampled:
            end_timestamp = time.time()
            # Collect additional annotations from the logging handler
            annotations_by_span_id = defaultdict(dict)
            binary_annotations_by_span_id = defaultdict(dict)
            for msg in self.log_handler.extra_annotations:
                span_id = msg['parent_span_id'] or self.zipkin_attrs.span_id
                # This should check if these are non-None
                annotations_by_span_id[span_id].update(msg['annotations'])
                binary_annotations_by_span_id[span_id].update(
                    msg['binary_annotations'])

            # Collect, annotate, and log client spans from the logging handler
            for span in self.log_handler.client_spans:
                # The parent_span_id is either the parent ID set in the
                # logging handler or the current Zipkin context's span ID.
                parent_span_id = (span['parent_span_id']
                                  or self.zipkin_attrs.span_id)
                # A new client span's span ID can be overridden
                span_id = span['span_id'] or generate_random_64bit_string()
                endpoint = copy_endpoint_with_new_service_name(
                    self.thrift_endpoint, span['service_name'])
                # Collect annotations both logged with the new spans and
                # logged in separate log messages.
                annotations = span['annotations']
                annotations.update(annotations_by_span_id[span_id])
                binary_annotations = span['binary_annotations']
                binary_annotations.update(
                    binary_annotations_by_span_id[span_id])

                timestamp, duration = get_local_span_timestamp_and_duration(
                    annotations)
                # Create serializable thrift objects of annotations
                thrift_annotations = annotation_list_builder(
                    annotations, endpoint)
                thrift_binary_annotations = binary_annotation_list_builder(
                    binary_annotations, endpoint)
                if span.get('sa_binary_annotations'):
                    thrift_binary_annotations += span['sa_binary_annotations']

                log_span(
                    span_id=span_id,
                    parent_span_id=parent_span_id,
                    trace_id=self.zipkin_attrs.trace_id,
                    span_name=span['span_name'],
                    annotations=thrift_annotations,
                    binary_annotations=thrift_binary_annotations,
                    transport_handler=self.transport_handler,
                    timestamp_s=timestamp,
                    duration_s=duration,
                )

            extra_annotations = annotations_by_span_id[
                self.zipkin_attrs.span_id]
            extra_binary_annotations = binary_annotations_by_span_id[
                self.zipkin_attrs.span_id]

            k1, k2 = ('sr', 'ss')
            if self.client_context:
                k1, k2 = ('cs', 'cr')
            annotations = {k1: self.start_timestamp, k2: end_timestamp}
            annotations.update(extra_annotations)

            if self.add_logging_annotation:
                annotations[LOGGING_END_KEY] = time.time()

            thrift_annotations = annotation_list_builder(
                annotations,
                self.thrift_endpoint,
            )

            # Binary annotations can be set through debug messages or the
            # set_extra_binary_annotations registry setting.
            self.binary_annotations_dict.update(extra_binary_annotations)
            thrift_binary_annotations = binary_annotation_list_builder(
                self.binary_annotations_dict,
                self.thrift_endpoint,
            )
            if self.sa_binary_annotations:
                thrift_binary_annotations += self.sa_binary_annotations

            if self.report_root_timestamp:
                timestamp = self.start_timestamp
                duration = end_timestamp - self.start_timestamp
            else:
                timestamp = duration = None

            log_span(
                span_id=self.zipkin_attrs.span_id,
                parent_span_id=self.zipkin_attrs.parent_span_id,
                trace_id=self.zipkin_attrs.trace_id,
                span_name=self.span_name,
                annotations=thrift_annotations,
                binary_annotations=thrift_binary_annotations,
                timestamp_s=timestamp,
                duration_s=duration,
                transport_handler=self.transport_handler,
            )
Пример #11
0
def test_annotation_list_builder(ann_mock):
    ann_list = {'foo': 1, 'bar': 2}
    thrift.annotation_list_builder(ann_list, 'host')
    ann_mock.assert_any_call(1000000, 'foo', 'host')
    ann_mock.assert_any_call(2000000, 'bar', 'host')
    assert ann_mock.call_count == 2
Пример #12
0
def check_v1_thrift(obj, zipkin_attrs, inner_span_id, ts):
    inner_span, producer_span, root_span = _decode_binary_thrift_objs(obj)

    endpoint = thrift.create_endpoint(
        port=8080, service_name="test_service_name", ipv4="10.0.0.0",
    )
    binary_annotations = thrift.binary_annotation_list_builder(
        {"some_key": "some_value"}, endpoint,
    )
    binary_annotations.append(
        thrift.create_binary_annotation(
            "sa",
            "\x01",
            zipkin_core.AnnotationType.BOOL,
            thrift.create_endpoint(
                port=8888,
                service_name="sa_service",
                ipv6="2001:0db8:85a3:0000:0000:8a2e:0370:7334",
            ),
        )
    )

    expected_root = thrift.create_span(
        span_id=zipkin_attrs.span_id,
        parent_span_id=zipkin_attrs.parent_span_id,
        trace_id=zipkin_attrs.trace_id,
        span_name="test_span_name",
        annotations=thrift.annotation_list_builder(
            OrderedDict([("cs", ts), ("cr", ts + 10)]), endpoint,
        ),
        binary_annotations=binary_annotations,
        timestamp_s=None,
        duration_s=None,
    )
    # py.test diffs of thrift Spans are pretty useless and hide many things
    # These prints would only appear on stdout if the test fails and help comparing
    # the 2 spans.
    print(root_span)
    print(expected_root)
    assert root_span == expected_root

    expected_inner = thrift.create_span(
        span_id=inner_span_id,
        parent_span_id=zipkin_attrs.span_id,
        trace_id=zipkin_attrs.trace_id,
        span_name="inner_span",
        annotations=thrift.annotation_list_builder(
            OrderedDict([("ws", ts)]), endpoint,
        ),
        binary_annotations=[],
        timestamp_s=ts,
        duration_s=5,
    )
    # py.test diffs of thrift Spans are pretty useless and hide many things
    # These prints would only appear on stdout if the test fails and help comparing
    # the 2 spans.
    print(inner_span)
    print(expected_inner)
    assert inner_span == expected_inner

    expected_producer = thrift.create_span(
        span_id=inner_span_id,
        parent_span_id=zipkin_attrs.span_id,
        trace_id=zipkin_attrs.trace_id,
        span_name="producer_span",
        annotations=thrift.annotation_list_builder(
            OrderedDict([("ms", ts)]), endpoint,
        ),
        binary_annotations=[],
        timestamp_s=ts,
        duration_s=10,
    )
    # py.test diffs of thrift Spans are pretty useless and hide many things
    # These prints would only appear on stdout if the test fails and help comparing
    # the 2 spans.
    print(producer_span)
    print(expected_producer)
    assert producer_span == expected_producer
Пример #13
0
def test_annotation_list_builder(ann_mock):
    ann_list = {"foo": 1, "bar": 2}
    thrift.annotation_list_builder(ann_list, "host")
    ann_mock.assert_any_call(1000000, "foo", "host")
    ann_mock.assert_any_call(2000000, "bar", "host")
    assert ann_mock.call_count == 2
Пример #14
0
    def add_span(
        self,
        span_id,
        parent_span_id,
        trace_id,
        span_name,
        annotations,
        binary_annotations,
        timestamp_s,
        duration_s,
        endpoint,
        sa_endpoint,
    ):
        thrift_endpoint = thrift.create_endpoint(
            endpoint.port,
            endpoint.service_name,
            endpoint.ipv4,
            endpoint.ipv6,
        )

        thrift_annotations = thrift.annotation_list_builder(
            annotations,
            thrift_endpoint,
        )

        # Binary annotations can be set through debug messages or the
        # set_extra_binary_annotations registry setting.
        thrift_binary_annotations = thrift.binary_annotation_list_builder(
            binary_annotations,
            thrift_endpoint,
        )

        # Add sa binary annotation
        if sa_endpoint is not None:
            thrift_sa_endpoint = thrift.create_endpoint(
                sa_endpoint.port,
                sa_endpoint.service_name,
                sa_endpoint.ipv4,
                sa_endpoint.ipv6,
            )
            thrift_binary_annotations.append(thrift.create_binary_annotation(
                key=thrift.zipkin_core.SERVER_ADDR,
                value=thrift.SERVER_ADDR_VAL,
                annotation_type=thrift.zipkin_core.AnnotationType.BOOL,
                host=thrift_sa_endpoint,
            ))

        thrift_span = thrift.create_span(
            span_id,
            parent_span_id,
            trace_id,
            span_name,
            thrift_annotations,
            thrift_binary_annotations,
            timestamp_s,
            duration_s,
        )

        encoded_span = thrift.span_to_bytes(thrift_span)

        # If we've already reached the max batch size or the new span doesn't
        # fit in max_payload_bytes, send what we've collected until now and
        # start a new batch.
        is_over_size_limit = (
            self.max_payload_bytes is not None and
            self.current_size + len(encoded_span) > self.max_payload_bytes
        )
        is_over_portion_limit = len(self.queue) >= self.max_portion_size
        if is_over_size_limit or is_over_portion_limit:
            self.flush()

        self.queue.append(encoded_span)
        self.current_size += len(encoded_span)