def test_valid_header(self):
        header = "{}/{};o=1".format(
            get_hexadecimal_trace_id(self.valid_trace_id), self.valid_span_id)
        new_span_context = self._extract(header)
        self.assertEqual(new_span_context.trace_id, self.valid_trace_id)
        self.assertEqual(new_span_context.span_id, self.valid_span_id)
        self.assertEqual(new_span_context.trace_flags, TraceFlags(1))
        self.assertTrue(new_span_context.is_remote)

        header = "{}/{};o=10".format(
            get_hexadecimal_trace_id(self.valid_trace_id), self.valid_span_id)
        new_span_context = self._extract(header)
        self.assertEqual(new_span_context.trace_id, self.valid_trace_id)
        self.assertEqual(new_span_context.span_id, self.valid_span_id)
        self.assertEqual(new_span_context.trace_flags, TraceFlags(10))
        self.assertTrue(new_span_context.is_remote)

        header = "{}/{};o=0".format(
            get_hexadecimal_trace_id(self.valid_trace_id), self.valid_span_id)
        new_span_context = self._extract(header)
        self.assertEqual(new_span_context.trace_id, self.valid_trace_id)
        self.assertEqual(new_span_context.span_id, self.valid_span_id)
        self.assertEqual(new_span_context.trace_flags, TraceFlags(0))
        self.assertTrue(new_span_context.is_remote)

        header = "{}/{};o=0".format(
            get_hexadecimal_trace_id(self.valid_trace_id), 345)
        new_span_context = self._extract(header)
        self.assertEqual(new_span_context.trace_id, self.valid_trace_id)
        self.assertEqual(new_span_context.span_id, 345)
        self.assertEqual(new_span_context.trace_flags, TraceFlags(0))
        self.assertTrue(new_span_context.is_remote)
コード例 #2
0
def _extract_links(links: Sequence[trace_api.Link]) -> ProtoSpan.Links:
    """Convert span.links"""
    if not links:
        return None
    extracted_links = []
    dropped_links = 0
    if len(links) > MAX_NUM_LINKS:
        logger.warning(
            "Exporting more then %s links, some will be truncated",
            MAX_NUM_LINKS,
        )
        dropped_links = len(links) - MAX_NUM_LINKS
        links = links[:MAX_NUM_LINKS]
    for link in links:
        link_attributes = link.attributes or {}
        if len(link_attributes) > MAX_LINK_ATTRS:
            logger.warning(
                "Link has more then %s attributes, some will be truncated",
                MAX_LINK_ATTRS,
            )
        trace_id = get_hexadecimal_trace_id(link.context.trace_id)
        span_id = get_hexadecimal_span_id(link.context.span_id)
        extracted_links.append({
            "trace_id":
            trace_id,
            "span_id":
            span_id,
            "type":
            "TYPE_UNSPECIFIED",
            "attributes":
            _extract_attributes(link_attributes, MAX_LINK_ATTRS),
        })
    return ProtoSpan.Links(link=extracted_links,
                           dropped_links_count=dropped_links)
コード例 #3
0
    def _translate_to_cloud_trace(
            self, spans: Sequence[Span]) -> List[Dict[str, Any]]:
        """Translate the spans to Cloud Trace format.

        Args:
            spans: Tuple of spans to convert
        """

        cloud_trace_spans = []

        for span in spans:
            ctx = span.get_context()
            trace_id = get_hexadecimal_trace_id(ctx.trace_id)
            span_id = get_hexadecimal_span_id(ctx.span_id)
            span_name = "projects/{}/traces/{}/spans/{}".format(
                self.project_id, trace_id, span_id)

            parent_id = None
            if span.parent:
                parent_id = get_hexadecimal_span_id(span.parent.span_id)

            start_time = _get_time_from_ns(span.start_time)
            end_time = _get_time_from_ns(span.end_time)

            if len(span.attributes) > MAX_SPAN_ATTRS:
                logger.warning(
                    "Span has more then %s attributes, some will be truncated",
                    MAX_SPAN_ATTRS,
                )

            cloud_trace_spans.append({
                "name":
                span_name,
                "span_id":
                span_id,
                "display_name":
                _get_truncatable_str_object(span.name, 128),
                "start_time":
                start_time,
                "end_time":
                end_time,
                "parent_span_id":
                parent_id,
                "attributes":
                _extract_attributes(span.attributes, MAX_SPAN_ATTRS),
                "links":
                _extract_links(span.links),
                "status":
                _extract_status(span.status),
                "time_events":
                _extract_events(span.events),
            })
            # TODO: Leverage more of the Cloud Trace API, e.g.
            #  same_process_as_parent_span and child_span_count

        return cloud_trace_spans
    def test_invalid_span_id(self):
        header = "{}/{};o={}".format(
            get_hexadecimal_trace_id(self.valid_trace_id), INVALID_SPAN_ID, 1)
        self.assertEqual(self._extract(header),
                         trace.INVALID_SPAN.get_span_context())

        header = "{}/{};o={}".format(
            get_hexadecimal_trace_id(self.valid_trace_id), "0" * 16, 1)
        self.assertEqual(self._extract(header),
                         trace.INVALID_SPAN.get_span_context())

        header = "{}/{};o={}".format(
            get_hexadecimal_trace_id(self.valid_trace_id), "0", 1)
        self.assertEqual(self._extract(header),
                         trace.INVALID_SPAN.get_span_context())

        header = "{}/{};o={}".format(
            get_hexadecimal_trace_id(self.valid_trace_id), self.too_long_id, 1)
        self.assertEqual(self._extract(header),
                         trace.INVALID_SPAN.get_span_context())
    def test_invalid_header_format(self):
        header = "invalid_header"
        self.assertEqual(self._extract(header),
                         trace.INVALID_SPAN.get_span_context())

        header = "{}/{};o=".format(
            get_hexadecimal_trace_id(self.valid_trace_id), self.valid_span_id)
        self.assertEqual(self._extract(header),
                         trace.INVALID_SPAN.get_span_context())

        header = "extra_chars/{}/{};o=1".format(
            get_hexadecimal_trace_id(self.valid_trace_id), self.valid_span_id)
        self.assertEqual(self._extract(header),
                         trace.INVALID_SPAN.get_span_context())

        header = "{}/{}extra_chars;o=1".format(
            get_hexadecimal_trace_id(self.valid_trace_id), self.valid_span_id)
        self.assertEqual(self._extract(header),
                         trace.INVALID_SPAN.get_span_context())

        header = "{}/{};o=1extra_chars".format(
            get_hexadecimal_trace_id(self.valid_trace_id), self.valid_span_id)
        self.assertEqual(self._extract(header),
                         trace.INVALID_SPAN.get_span_context())

        header = "{}/;o=1".format(get_hexadecimal_trace_id(
            self.valid_trace_id))
        self.assertEqual(self._extract(header),
                         trace.INVALID_SPAN.get_span_context())

        header = "/{};o=1".format(self.valid_span_id)
        self.assertEqual(self._extract(header),
                         trace.INVALID_SPAN.get_span_context())

        header = "{}/{};o={}".format("123", "34", "4")
        self.assertEqual(self._extract(header),
                         trace.INVALID_SPAN.get_span_context())
 def test_inject_with_valid_context(self):
     span_context = SpanContext(
         trace_id=self.valid_trace_id,
         span_id=self.valid_span_id,
         is_remote=True,
         trace_flags=TraceFlags(1),
     )
     output = self._inject(trace.DefaultSpan(span_context))
     self.assertEqual(
         output,
         "{}/{};o={}".format(
             get_hexadecimal_trace_id(self.valid_trace_id),
             self.valid_span_id,
             1,
         ),
     )
コード例 #7
0
    def inject(
        self,
        set_in_carrier: httptextformat.Setter[httptextformat.HTTPTextFormatT],
        carrier: httptextformat.HTTPTextFormatT,
        context: typing.Optional[Context] = None,
    ) -> None:
        span = trace.get_current_span(context)
        span_context = span.get_context()
        if span_context == trace.INVALID_SPAN_CONTEXT:
            return

        header = "{}/{};o={}".format(
            get_hexadecimal_trace_id(span_context.trace_id),
            span_context.span_id,
            int(span_context.trace_flags.sampled),
        )
        set_in_carrier(carrier, _TRACE_CONTEXT_HEADER_NAME, header)
    def test_mixed_case_header_key(self):
        header_value = "{}/{};o=1".format(
            get_hexadecimal_trace_id(self.valid_trace_id), self.valid_span_id)

        for header_key in (
                "X-Cloud-Trace-Context",
                "X-ClOuD-tRace-ConTeXt",
                "X-CLOUD-TRACE-CONTEXT",
        ):
            header_map = {header_key: [header_value]}
            new_context = self.propagator.extract(dict_getter, header_map)
            new_span_context = trace.get_current_span(
                new_context).get_span_context()
            self.assertEqual(new_span_context.trace_id, self.valid_trace_id)
            self.assertEqual(new_span_context.span_id, self.valid_span_id)
            self.assertEqual(new_span_context.trace_flags, TraceFlags(1))
            self.assertTrue(new_span_context.is_remote)
コード例 #9
0
    def _translate_to_cloud_trace(
            self, spans: Sequence[Span]) -> List[Dict[str, Any]]:
        """Translate the spans to Cloud Trace format.

        Args:
            spans: Sequence of spans to convert
        """

        cloud_trace_spans = []

        for span in spans:
            ctx = span.get_span_context()
            trace_id = get_hexadecimal_trace_id(ctx.trace_id)
            span_id = get_hexadecimal_span_id(ctx.span_id)
            span_name = "projects/{}/traces/{}/spans/{}".format(
                self.project_id, trace_id, span_id)

            parent_id = None
            if span.parent:
                parent_id = get_hexadecimal_span_id(span.parent.span_id)

            start_time = _get_time_from_ns(span.start_time)
            end_time = _get_time_from_ns(span.end_time)

            if len(span.attributes) > MAX_SPAN_ATTRS:
                logger.warning(
                    "Span has more then %s attributes, some will be truncated",
                    MAX_SPAN_ATTRS,
                )

            # Span does not support a MonitoredResource object. We put the
            # information into attributes instead.
            resources_and_attrs = _extract_resources(span.resource)
            resources_and_attrs.update(span.attributes)

            cloud_trace_spans.append({
                "name":
                span_name,
                "span_id":
                span_id,
                "display_name":
                _get_truncatable_str_object(span.name, 128),
                "start_time":
                start_time,
                "end_time":
                end_time,
                "parent_span_id":
                parent_id,
                "attributes":
                _extract_attributes(
                    resources_and_attrs,
                    MAX_SPAN_ATTRS,
                    add_agent_attr=True,
                ),
                "links":
                _extract_links(span.links),  # type: ignore[has-type]
                "status":
                _extract_status(span.status),  # type: ignore[arg-type]
                "time_events":
                _extract_events(span.events),
                "span_kind":
                _extract_span_kind(span.kind),
            })
            # TODO: Leverage more of the Cloud Trace API, e.g.
            #  same_process_as_parent_span and child_span_count

        return cloud_trace_spans