Ejemplo n.º 1
0
 def setUpClass(cls):
     cls.serialized_trace_id = b3_format.format_trace_id(
         trace.generate_trace_id())
     cls.serialized_span_id = b3_format.format_span_id(
         trace.generate_span_id())
     cls.serialized_parent_id = b3_format.format_span_id(
         trace.generate_span_id())
Ejemplo n.º 2
0
    def test_links(self):
        other_context1 = trace_api.SpanContext(
            trace_id=trace.generate_trace_id(),
            span_id=trace.generate_span_id(),
        )
        other_context2 = trace_api.SpanContext(
            trace_id=trace.generate_trace_id(),
            span_id=trace.generate_span_id(),
        )
        other_context3 = trace_api.SpanContext(
            trace_id=trace.generate_trace_id(),
            span_id=trace.generate_span_id(),
        )
        links = [
            trace_api.Link(other_context1),
            trace_api.Link(other_context2, {"name": "neighbor"}),
            trace_api.Link(other_context3, {"component": "http"}),
        ]
        with self.tracer.start_as_current_span("root", links=links) as root:

            self.assertEqual(len(root.links), 3)
            self.assertEqual(root.links[0].context.trace_id,
                             other_context1.trace_id)
            self.assertEqual(root.links[0].context.span_id,
                             other_context1.span_id)
            self.assertEqual(root.links[0].attributes, {})
            self.assertEqual(root.links[1].context.trace_id,
                             other_context2.trace_id)
            self.assertEqual(root.links[1].context.span_id,
                             other_context2.span_id)
            self.assertEqual(root.links[1].attributes, {"name": "neighbor"})
            self.assertEqual(root.links[2].context.span_id,
                             other_context3.span_id)
            self.assertEqual(root.links[2].attributes, {"component": "http"})
Ejemplo n.º 3
0
    def test_links(self):
        other_context1 = trace_api.SpanContext(
            trace_id=trace.generate_trace_id(),
            span_id=trace.generate_span_id(),
            is_remote=False,
        )
        other_context2 = trace_api.SpanContext(
            trace_id=trace.generate_trace_id(),
            span_id=trace.generate_span_id(),
            is_remote=False,
        )

        links = (
            trace_api.Link(other_context1),
            trace_api.Link(other_context2, {"name": "neighbor"}),
        )
        with self.tracer.start_as_current_span("root", links=links) as root:

            self.assertEqual(len(root.links), 2)
            self.assertEqual(
                root.links[0].context.trace_id, other_context1.trace_id
            )
            self.assertEqual(
                root.links[0].context.span_id, other_context1.span_id
            )
            self.assertEqual(root.links[0].attributes, None)
            self.assertEqual(
                root.links[1].context.trace_id, other_context2.trace_id
            )
            self.assertEqual(
                root.links[1].context.span_id, other_context2.span_id
            )
            self.assertEqual(root.links[1].attributes, {"name": "neighbor"})
Ejemplo n.º 4
0
    def test_sampling_priority_auto_reject(self):
        """Test sampling priority rejected."""
        parent_context = get_current_span(
            FORMAT.extract(
                get_as_list,
                {
                    FORMAT.TRACE_ID_KEY: self.serialized_trace_id,
                    FORMAT.PARENT_ID_KEY: self.serialized_parent_id,
                    FORMAT.SAMPLING_PRIORITY_KEY: str(constants.AUTO_REJECT),
                },
            )).get_context()

        self.assertEqual(parent_context.trace_flags, constants.AUTO_REJECT)

        child = trace.Span(
            "child",
            trace_api.SpanContext(
                parent_context.trace_id,
                trace.generate_span_id(),
                is_remote=False,
                trace_flags=parent_context.trace_flags,
                trace_state=parent_context.trace_state,
            ),
            parent=parent_context,
        )

        child_carrier = {}
        child_context = set_span_in_context(child)
        FORMAT.inject(dict.__setitem__, child_carrier, context=child_context)

        self.assertEqual(
            child_carrier[FORMAT.SAMPLING_PRIORITY_KEY],
            str(constants.AUTO_REJECT),
        )
 def test_full_path(self):
     trace_id = trace_sdk.generate_trace_id()
     # We need to use the Werkzeug test app because
     # The headers are injected at the wsgi layer.
     # The flask test app will not include these, and
     # result in the values not propagated.
     client = Client(self.app.wsgi_app, BaseResponse)
     # emulate b3 headers
     client.get(
         "/",
         headers={
             "traceparent":
             "00-{:032x}-{:016x}-{:02x}".format(
                 trace_id,
                 trace_sdk.generate_span_id(),
                 trace.TraceFlags.SAMPLED,
             )
         },
     )
     # assert the http request header was propagated through.
     prepared_request = self.send.call_args[0][1]
     headers = prepared_request.headers
     self.assertRegex(
         headers["traceparent"],
         r"00-{:032x}-[0-9a-f]{{16}}-01".format(trace_id),
     )
Ejemplo n.º 6
0
    def test_ended_span(self):
        """"Events, attributes are not allowed after span is ended"""
        tracer = trace.Tracer("test_ended_span")

        other_context1 = trace_api.SpanContext(
            trace_id=trace.generate_trace_id(),
            span_id=trace.generate_span_id(),
        )

        with tracer.start_span("root") as root:
            # everything should be empty at the beginning
            self.assertEqual(len(root.attributes), 0)
            self.assertEqual(len(root.events), 0)
            self.assertEqual(len(root.links), 0)

            # call end first time
            root.end()
            end_time0 = root.end_time

            # call it a second time
            root.end()
            # end time shouldn't be changed
            self.assertEqual(end_time0, root.end_time)

            root.set_attribute("component", "http")
            self.assertEqual(len(root.attributes), 0)

            root.add_event("event1")
            self.assertEqual(len(root.events), 0)

            root.add_link(other_context1)
            self.assertEqual(len(root.links), 0)

            root.update_name("xxx")
            self.assertEqual(root.name, "root")
Ejemplo n.º 7
0
    def test_links(self):
        other_context1 = trace_api.SpanContext(
            trace_id=trace.generate_trace_id(),
            span_id=trace.generate_span_id(),
            is_remote=False,
        )
        other_context2 = trace_api.SpanContext(
            trace_id=trace.generate_trace_id(),
            span_id=trace.generate_span_id(),
            is_remote=False,
        )
        other_context3 = trace_api.SpanContext(
            trace_id=trace.generate_trace_id(),
            span_id=trace.generate_span_id(),
            is_remote=False,
        )

        def get_link_attributes():
            return {"component": "http"}

        links = (
            trace_api.Link(other_context1),
            trace_api.Link(other_context2, {"name": "neighbor"}),
            trace_api.LazyLink(other_context3, get_link_attributes),
        )
        with self.tracer.start_as_current_span("root", links=links) as root:

            self.assertEqual(len(root.links), 3)
            self.assertEqual(
                root.links[0].context.trace_id, other_context1.trace_id
            )
            self.assertEqual(
                root.links[0].context.span_id, other_context1.span_id
            )
            self.assertEqual(root.links[0].attributes, None)
            self.assertEqual(
                root.links[1].context.trace_id, other_context2.trace_id
            )
            self.assertEqual(
                root.links[1].context.span_id, other_context2.span_id
            )
            self.assertEqual(root.links[1].attributes, {"name": "neighbor"})
            self.assertEqual(
                root.links[2].context.span_id, other_context3.span_id
            )
            self.assertEqual(root.links[2].attributes, {"component": "http"})
Ejemplo n.º 8
0
 def setUpClass(cls):
     cls.serialized_trace_id = propagator.format_trace_id(
         trace.generate_trace_id()
     )
     cls.serialized_parent_id = propagator.format_span_id(
         trace.generate_span_id()
     )
     cls.serialized_origin = "origin-service"
Ejemplo n.º 9
0
    def test_context_propagation(self):
        """Test the propagation of Datadog headers."""
        parent_context = get_span_from_context(
            FORMAT.extract(
                get_as_list,
                {
                    FORMAT.TRACE_ID_KEY: self.serialized_trace_id,
                    FORMAT.PARENT_ID_KEY: self.serialized_parent_id,
                    FORMAT.SAMPLING_PRIORITY_KEY: str(constants.AUTO_KEEP),
                    FORMAT.ORIGIN_KEY: self.serialized_origin,
                },
            )
        ).get_context()

        self.assertEqual(
            parent_context.trace_id, int(self.serialized_trace_id)
        )
        self.assertEqual(
            parent_context.span_id, int(self.serialized_parent_id)
        )
        self.assertEqual(parent_context.trace_flags, constants.AUTO_KEEP)
        self.assertEqual(
            parent_context.trace_state.get(constants.DD_ORIGIN),
            self.serialized_origin,
        )
        self.assertTrue(parent_context.is_remote)

        child = trace.Span(
            "child",
            trace_api.SpanContext(
                parent_context.trace_id,
                trace.generate_span_id(),
                is_remote=False,
                trace_flags=parent_context.trace_flags,
                trace_state=parent_context.trace_state,
            ),
            parent=parent_context,
        )

        child_carrier = {}
        child_context = set_span_in_context(child)
        FORMAT.inject(dict.__setitem__, child_carrier, context=child_context)

        self.assertEqual(
            child_carrier[FORMAT.TRACE_ID_KEY], self.serialized_trace_id
        )
        self.assertEqual(
            child_carrier[FORMAT.PARENT_ID_KEY], str(child.context.span_id)
        )
        self.assertEqual(
            child_carrier[FORMAT.SAMPLING_PRIORITY_KEY],
            str(constants.AUTO_KEEP),
        )
        self.assertEqual(
            child_carrier.get(FORMAT.ORIGIN_KEY), self.serialized_origin
        )
Ejemplo n.º 10
0
    def test_ended_span(self):
        """"Events, attributes are not allowed after span is ended"""
        tracer = trace.Tracer("test_ended_span")

        other_context1 = trace_api.SpanContext(
            trace_id=trace.generate_trace_id(),
            span_id=trace.generate_span_id(),
        )

        with tracer.start_as_current_span("root") as root:
            # everything should be empty at the beginning
            self.assertEqual(len(root.attributes), 0)
            self.assertEqual(len(root.events), 0)
            self.assertEqual(len(root.links), 0)

            # call end first time
            root.end()
            end_time0 = root.end_time

            # call it a second time
            root.end()
            # end time shouldn't be changed
            self.assertEqual(end_time0, root.end_time)

            root.set_attribute("component", "http")
            self.assertEqual(len(root.attributes), 0)

            root.add_event("event1")
            self.assertEqual(len(root.events), 0)

            root.add_link(other_context1)
            self.assertEqual(len(root.links), 0)

            root.update_name("xxx")
            self.assertEqual(root.name, "root")

            new_status = trace_api.status.Status(
                trace_api.status.StatusCanonicalCode.CANCELLED,
                "Test description",
            )
            root.set_status(new_status)
            # default status
            self.assertTrue(root.status.is_ok)
            self.assertEqual(
                root.status.canonical_code,
                trace_api.status.StatusCanonicalCode.OK,
            )
            self.assertIs(root.status.description, None)
Ejemplo n.º 11
0
def get_child_parent_new_carrier(old_carrier):

    parent_context = FORMAT.extract(get_as_list, old_carrier)

    parent = trace.Span("parent", parent_context)
    child = trace.Span(
        "child",
        trace_api.SpanContext(
            parent_context.trace_id,
            trace.generate_span_id(),
            trace_flags=parent_context.trace_flags,
            trace_state=parent_context.trace_state,
        ),
        parent=parent,
    )

    new_carrier = {}
    FORMAT.inject(child, dict.__setitem__, new_carrier)

    return child, parent, new_carrier
Ejemplo n.º 12
0
def get_child_parent_new_carrier(old_carrier):

    ctx = FORMAT.extract(get_as_list, old_carrier)
    parent_context = get_span_from_context(ctx).get_context()

    parent = trace.Span("parent", parent_context)
    child = trace.Span(
        "child",
        trace_api.SpanContext(
            parent_context.trace_id,
            trace.generate_span_id(),
            is_remote=False,
            trace_flags=parent_context.trace_flags,
            trace_state=parent_context.trace_state,
        ),
        parent=parent,
    )

    new_carrier = {}
    ctx = set_span_in_context(child)
    FORMAT.inject(dict.__setitem__, new_carrier, context=ctx)

    return child, parent, new_carrier
Ejemplo n.º 13
0
 def test_full_path(self):
     trace_id = trace.generate_trace_id()
     # We need to use the Werkzeug test app because
     # The headers are injected at the wsgi layer.
     # The flask test app will not include these, and
     # result in the values not propagated.
     client = Client(self.app.wsgi_app, BaseResponse)
     # emulate b3 headers
     client.get(
         "/",
         headers={
             "x-b3-traceid": b3_format.format_trace_id(trace_id),
             "x-b3-spanid":
             b3_format.format_span_id(trace.generate_span_id()),
             "x-b3-sampled": "1",
         },
     )
     # assert the http request header was propagated through.
     prepared_request = self.send.call_args[0][1]
     headers = prepared_request.headers
     for required_header in {"x-b3-traceid", "x-b3-spanid", "x-b3-sampled"}:
         self.assertIn(required_header, headers)
     self.assertEqual(headers["x-b3-traceid"],
                      b3_format.format_trace_id(trace_id))
Ejemplo n.º 14
0
    def extract(
        self,
        get_from_carrier: Getter[HTTPTextFormatT],
        carrier: HTTPTextFormatT,
        context: typing.Optional[Context] = None,
    ) -> Context:
        trace_id = format_trace_id(trace.INVALID_TRACE_ID)
        span_id = format_span_id(trace.INVALID_SPAN_ID)
        sampled = "0"
        flags = None

        single_header = _extract_first_element(
            get_from_carrier(carrier, self.SINGLE_HEADER_KEY))
        if single_header:
            # The b3 spec calls for the sampling state to be
            # "deferred", which is unspecified. This concept does not
            # translate to SpanContext, so we set it as recorded.
            sampled = "1"
            fields = single_header.split("-", 4)

            if len(fields) == 1:
                sampled = fields[0]
            elif len(fields) == 2:
                trace_id, span_id = fields
            elif len(fields) == 3:
                trace_id, span_id, sampled = fields
            elif len(fields) == 4:
                trace_id, span_id, sampled, _ = fields
            else:
                return trace.set_span_in_context(trace.INVALID_SPAN)
        else:
            trace_id = (_extract_first_element(
                get_from_carrier(carrier, self.TRACE_ID_KEY)) or trace_id)
            span_id = (_extract_first_element(
                get_from_carrier(carrier, self.SPAN_ID_KEY)) or span_id)
            sampled = (_extract_first_element(
                get_from_carrier(carrier, self.SAMPLED_KEY)) or sampled)
            flags = (_extract_first_element(
                get_from_carrier(carrier, self.FLAGS_KEY)) or flags)

        if (self._trace_id_regex.fullmatch(trace_id) is None
                or self._span_id_regex.fullmatch(span_id) is None):
            trace_id = generate_trace_id()
            span_id = generate_span_id()
            sampled = "0"

        else:
            trace_id = int(trace_id, 16)
            span_id = int(span_id, 16)

        options = 0
        # The b3 spec provides no defined behavior for both sample and
        # flag values set. Since the setting of at least one implies
        # the desire for some form of sampling, propagate if either
        # header is set to allow.
        if sampled in self._SAMPLE_PROPAGATE_VALUES or flags == "1":
            options |= trace.TraceFlags.SAMPLED

        return trace.set_span_in_context(
            trace.DefaultSpan(
                trace.SpanContext(
                    # trace an span ids are encoded in hex, so must be converted
                    trace_id=trace_id,
                    span_id=span_id,
                    is_remote=True,
                    trace_flags=trace.TraceFlags(options),
                    trace_state=trace.TraceState(),
                )))
Ejemplo n.º 15
0
    def test_span_members(self):
        tracer = trace.Tracer("test_span_members")

        other_context1 = trace_api.SpanContext(
            trace_id=trace.generate_trace_id(),
            span_id=trace.generate_span_id(),
        )
        other_context2 = trace_api.SpanContext(
            trace_id=trace.generate_trace_id(),
            span_id=trace.generate_span_id(),
        )

        self.assertIsNone(tracer.get_current_span())

        with tracer.start_span("root") as root:
            root.set_attribute("component", "http")
            root.set_attribute("http.method", "GET")
            root.set_attribute("http.url",
                               "https://example.com:779/path/12/?q=d#123")
            root.set_attribute("http.status_code", 200)
            root.set_attribute("http.status_text", "OK")
            root.set_attribute("misc.pi", 3.14)

            # Setting an attribute with the same key as an existing attribute
            # SHOULD overwrite the existing attribute's value.
            root.set_attribute("attr-key", "attr-value1")
            root.set_attribute("attr-key", "attr-value2")

            root.add_event("event0")
            root.add_event("event1", {"name": "birthday"})

            root.add_link(other_context1)
            root.add_link(other_context2, {"name": "neighbor"})

            root.update_name("toor")
            self.assertEqual(root.name, "toor")

            # The public API does not expose getters.
            # Checks by accessing the span members directly

            self.assertEqual(len(root.attributes), 7)
            self.assertEqual(root.attributes["component"], "http")
            self.assertEqual(root.attributes["http.method"], "GET")
            self.assertEqual(
                root.attributes["http.url"],
                "https://example.com:779/path/12/?q=d#123",
            )
            self.assertEqual(root.attributes["http.status_code"], 200)
            self.assertEqual(root.attributes["http.status_text"], "OK")
            self.assertEqual(root.attributes["misc.pi"], 3.14)
            self.assertEqual(root.attributes["attr-key"], "attr-value2")

            self.assertEqual(len(root.events), 2)
            self.assertEqual(root.events[0],
                             trace.Event(name="event0", attributes={}))
            self.assertEqual(
                root.events[1],
                trace.Event(name="event1", attributes={"name": "birthday"}),
            )

            self.assertEqual(len(root.links), 2)
            self.assertEqual(root.links[0].context.trace_id,
                             other_context1.trace_id)
            self.assertEqual(root.links[0].context.span_id,
                             other_context1.span_id)
            self.assertEqual(root.links[0].attributes, {})
            self.assertEqual(root.links[1].context.trace_id,
                             other_context2.trace_id)
            self.assertEqual(root.links[1].context.span_id,
                             other_context2.span_id)
            self.assertEqual(root.links[1].attributes, {"name": "neighbor"})
Ejemplo n.º 16
0
    def test_span_members(self):
        tracer = trace.Tracer("test_span_members")

        other_context1 = trace_api.SpanContext(
            trace_id=trace.generate_trace_id(),
            span_id=trace.generate_span_id(),
        )
        other_context2 = trace_api.SpanContext(
            trace_id=trace.generate_trace_id(),
            span_id=trace.generate_span_id(),
        )
        other_context3 = trace_api.SpanContext(
            trace_id=trace.generate_trace_id(),
            span_id=trace.generate_span_id(),
        )

        self.assertIsNone(tracer.get_current_span())

        with tracer.start_span("root") as root:
            # attributes
            root.set_attribute("component", "http")
            root.set_attribute("http.method", "GET")
            root.set_attribute("http.url",
                               "https://example.com:779/path/12/?q=d#123")
            root.set_attribute("http.status_code", 200)
            root.set_attribute("http.status_text", "OK")
            root.set_attribute("misc.pi", 3.14)

            # Setting an attribute with the same key as an existing attribute
            # SHOULD overwrite the existing attribute's value.
            root.set_attribute("attr-key", "attr-value1")
            root.set_attribute("attr-key", "attr-value2")

            self.assertEqual(len(root.attributes), 7)
            self.assertEqual(root.attributes["component"], "http")
            self.assertEqual(root.attributes["http.method"], "GET")
            self.assertEqual(
                root.attributes["http.url"],
                "https://example.com:779/path/12/?q=d#123",
            )
            self.assertEqual(root.attributes["http.status_code"], 200)
            self.assertEqual(root.attributes["http.status_text"], "OK")
            self.assertEqual(root.attributes["misc.pi"], 3.14)
            self.assertEqual(root.attributes["attr-key"], "attr-value2")

            # events
            root.add_event("event0")
            root.add_event("event1", {"name": "birthday"})
            now = util.time_ns()
            root.add_lazy_event(
                trace_api.Event("event2", now, {"name": "hello"}))

            self.assertEqual(len(root.events), 3)

            self.assertEqual(root.events[0].name, "event0")
            self.assertEqual(root.events[0].attributes, {})

            self.assertEqual(root.events[1].name, "event1")
            self.assertEqual(root.events[1].attributes, {"name": "birthday"})

            self.assertEqual(root.events[2].name, "event2")
            self.assertEqual(root.events[2].attributes, {"name": "hello"})
            self.assertEqual(root.events[2].timestamp, now)

            # links
            root.add_link(other_context1)
            root.add_link(other_context2, {"name": "neighbor"})
            root.add_lazy_link(
                trace_api.Link(other_context3, {"component": "http"}))

            self.assertEqual(len(root.links), 3)
            self.assertEqual(root.links[0].context.trace_id,
                             other_context1.trace_id)
            self.assertEqual(root.links[0].context.span_id,
                             other_context1.span_id)
            self.assertEqual(root.links[0].attributes, {})
            self.assertEqual(root.links[1].context.trace_id,
                             other_context2.trace_id)
            self.assertEqual(root.links[1].context.span_id,
                             other_context2.span_id)
            self.assertEqual(root.links[1].attributes, {"name": "neighbor"})
            self.assertEqual(root.links[2].context.span_id,
                             other_context3.span_id)
            self.assertEqual(root.links[2].attributes, {"component": "http"})

            # name
            root.update_name("toor")
            self.assertEqual(root.name, "toor")