def extract(
        self,
        carrier: CarrierT,
        context: Optional[Context] = None,
        getter: Getter = default_getter,
    ) -> Context:
        if context is None:
            context = Context()

        traceid = _extract_identifier(
            getter.get(carrier, OT_TRACE_ID_HEADER),
            _valid_extract_traceid,
            INVALID_TRACE_ID,
        )

        spanid = _extract_identifier(
            getter.get(carrier, OT_SPAN_ID_HEADER),
            _valid_extract_spanid,
            INVALID_SPAN_ID,
        )

        sampled = _extract_first_element(
            getter.get(carrier, OT_SAMPLED_HEADER)
        )

        if sampled == "true":
            traceflags = TraceFlags.SAMPLED
        else:
            traceflags = TraceFlags.DEFAULT

        if traceid != INVALID_TRACE_ID and spanid != INVALID_SPAN_ID:
            context = set_span_in_context(
                NonRecordingSpan(
                    SpanContext(
                        trace_id=traceid,
                        span_id=spanid,
                        is_remote=True,
                        trace_flags=TraceFlags(traceflags),
                    )
                ),
                context,
            )

            baggage = get_all(context) or {}

            for key in getter.keys(carrier):

                if not key.startswith(OT_BAGGAGE_PREFIX):
                    continue

                baggage[
                    key[len(OT_BAGGAGE_PREFIX) :]
                ] = _extract_first_element(getter.get(carrier, key))

            for key, value in baggage.items():
                context = set_baggage(key, value, context)

        return context
    def extract(
        self,
        carrier: textmap.CarrierT,
        context: typing.Optional[Context] = None,
        getter: textmap.Getter = textmap.default_getter,
    ) -> Context:
        """Extracts SpanContext from the carrier.

        See `opentelemetry.propagators.textmap.TextMapPropagator.extract`
        """
        if context is None:
            context = Context()

        header = getter.get(carrier, self._TRACEPARENT_HEADER_NAME)

        if not header:
            return context

        match = re.search(self._TRACEPARENT_HEADER_FORMAT_RE, header[0])
        if not match:
            return context

        version = match.group(1)
        trace_id = match.group(2)
        span_id = match.group(3)
        trace_flags = match.group(4)

        if trace_id == "0" * 32 or span_id == "0" * 16:
            return context

        if version == "00":
            if match.group(5):
                return context
        if version == "ff":
            return context

        tracestate_headers = getter.get(carrier, self._TRACESTATE_HEADER_NAME)
        if tracestate_headers is None:
            tracestate = None
        else:
            tracestate = TraceState.from_header(tracestate_headers)

        span_context = trace.SpanContext(
            trace_id=int(trace_id, 16),
            span_id=int(span_id, 16),
            is_remote=True,
            trace_flags=trace.TraceFlags(trace_flags),
            trace_state=tracestate,
        )
        return trace.set_span_in_context(trace.NonRecordingSpan(span_context),
                                         context)
Exemple #3
0
    def _get_header_value(
        getter: textmap.Getter, carrier: textmap.CarrierT,
    ) -> typing.Optional[str]:
        # first try all lowercase header
        header = getter.get(carrier, _TRACE_CONTEXT_HEADER_NAME)
        if header:
            return header[0]

        # otherwise try to find in keys for mixed case
        for key in getter.keys(carrier):
            if key.lower() == _TRACE_CONTEXT_HEADER_NAME:
                header = getter.get(carrier, key)
                if header:
                    return header[0]
        return None
Exemple #4
0
    def extract(
        self,
        carrier: CarrierT,
        context: typing.Optional[Context] = None,
        getter: Getter = default_getter,
    ) -> Context:

        if context is None:
            context = Context()
        header = getter.get(carrier, self.TRACE_ID_KEY)
        if not header:
            return context

        context = self._extract_baggage(getter, carrier, context)

        trace_id, span_id, flags = _parse_trace_id_header(header)
        if (trace_id == trace.INVALID_TRACE_ID
                or span_id == trace.INVALID_SPAN_ID):
            return context

        span = trace.NonRecordingSpan(
            trace.SpanContext(
                trace_id=trace_id,
                span_id=span_id,
                is_remote=True,
                trace_flags=trace.TraceFlags(flags & trace.TraceFlags.SAMPLED),
            ))
        return trace.set_span_in_context(span, context)
    def extract(
        self,
        carrier: CarrierT,
        context: typing.Optional[Context] = None,
        getter: Getter = default_getter,
    ) -> Context:
        if context is None:
            context = Context()

        trace_id = extract_first_element(getter.get(carrier,
                                                    self.TRACE_ID_KEY))

        span_id = extract_first_element(getter.get(carrier,
                                                   self.PARENT_ID_KEY))

        sampled = extract_first_element(
            getter.get(carrier, self.SAMPLING_PRIORITY_KEY))

        origin = extract_first_element(getter.get(carrier, self.ORIGIN_KEY))

        trace_flags = trace.TraceFlags()
        if sampled and int(sampled) in (
                constants.AUTO_KEEP,
                constants.USER_KEEP,
        ):
            trace_flags = trace.TraceFlags(trace.TraceFlags.SAMPLED)

        if trace_id is None or span_id is None:
            return context

        trace_state = []
        if origin is not None:
            trace_state.append((constants.DD_ORIGIN, origin))
        span_context = trace.SpanContext(
            trace_id=int(trace_id),
            span_id=int(span_id),
            is_remote=True,
            trace_flags=trace_flags,
            trace_state=trace.TraceState(trace_state),
        )

        return set_span_in_context(trace.NonRecordingSpan(span_context),
                                   context)
    def extract(
        self,
        carrier: CarrierT,
        context: typing.Optional[Context] = None,
        getter: Getter = default_getter,
    ) -> Context:
        trace_id_list = getter.get(carrier, self.TRACE_ID_KEY)
        span_id_list = getter.get(carrier, self.SPAN_ID_KEY)

        if not trace_id_list or not span_id_list:
            return trace.set_span_in_context(trace.INVALID_SPAN)

        return trace.set_span_in_context(
            trace.NonRecordingSpan(
                trace.SpanContext(
                    trace_id=int(trace_id_list[0]),
                    span_id=int(span_id_list[0]),
                    is_remote=True,
                )
            )
        )
    def extract(
        self,
        carrier: CarrierT,
        context: typing.Optional[Context] = None,
        getter: Getter = default_getter,
    ) -> Context:
        if context is None:
            context = Context()

        trace_header_list = getter.get(carrier, TRACE_HEADER_KEY)

        if not trace_header_list or len(trace_header_list) != 1:
            return context

        trace_header = trace_header_list[0]

        if not trace_header:
            return context

        try:
            (
                trace_id,
                span_id,
                sampled,
            ) = AwsXRayPropagator._extract_span_properties(trace_header)
        except AwsParseTraceHeaderError as err:
            _logger.debug(err.message)
            return context

        options = 0
        if sampled:
            options |= trace.TraceFlags.SAMPLED

        span_context = trace.SpanContext(
            trace_id=trace_id,
            span_id=span_id,
            is_remote=True,
            trace_flags=trace.TraceFlags(options),
            trace_state=trace.TraceState(),
        )

        if not span_context.is_valid:
            _logger.debug(
                "Invalid Span Extracted. Inserting INVALID span into provided context."
            )
            return context

        return trace.set_span_in_context(
            trace.NonRecordingSpan(span_context), context=context
        )
    def extract(
        self,
        carrier: textmap.CarrierT,
        context: typing.Optional[Context] = None,
        getter: textmap.Getter = textmap.default_getter,
    ) -> Context:
        """Extract Baggage from the carrier.

        See
        `opentelemetry.propagators.textmap.TextMapPropagator.extract`
        """

        if context is None:
            context = get_current()

        header = _extract_first_element(
            getter.get(carrier, self._BAGGAGE_HEADER_NAME)
        )

        if not header or len(header) > self._MAX_HEADER_LENGTH:
            return context

        baggage_entries = header.split(",")
        total_baggage_entries = self._MAX_PAIRS
        for entry in baggage_entries:
            if total_baggage_entries <= 0:
                return context
            total_baggage_entries -= 1
            if len(entry) > self._MAX_PAIR_LENGTH:
                continue
            try:
                name, value = entry.split("=", 1)
            except Exception:  # pylint: disable=broad-except
                continue
            context = baggage.set_baggage(
                urllib.parse.unquote(name).strip(),
                urllib.parse.unquote(value).strip(),
                context=context,
            )

        return context
Exemple #9
0
    def extract(
        self,
        carrier: CarrierT,
        context: typing.Optional[Context] = None,
        getter: Getter = default_getter,
    ) -> Context:

        if context is None:
            context = get_current()
        header = getter.get(carrier, self.TRACE_ID_KEY)
        if not header:
            return trace.set_span_in_context(trace.INVALID_SPAN, context)
        fields = _extract_first_element(header).split(":")

        context = self._extract_baggage(getter, carrier, context)
        if len(fields) != 4:
            return trace.set_span_in_context(trace.INVALID_SPAN, context)

        trace_id, span_id, _parent_id, flags = fields
        if (
            trace_id == trace.INVALID_TRACE_ID
            or span_id == trace.INVALID_SPAN_ID
        ):
            return trace.set_span_in_context(trace.INVALID_SPAN, context)

        span = trace.NonRecordingSpan(
            trace.SpanContext(
                trace_id=int(trace_id, 16),
                span_id=int(span_id, 16),
                is_remote=True,
                trace_flags=trace.TraceFlags(
                    int(flags, 16) & trace.TraceFlags.SAMPLED
                ),
            )
        )
        return trace.set_span_in_context(span, context)
    def extract(
        self,
        carrier: textmap.CarrierT,
        context: Optional[Context] = None,
        getter: textmap.Getter = textmap.default_getter,
    ) -> Context:
        """Extract Baggage from the carrier.

        See
        `opentelemetry.propagators.textmap.TextMapPropagator.extract`
        """

        if context is None:
            context = get_current()

        header = _extract_first_element(
            getter.get(carrier, self._BAGGAGE_HEADER_NAME)
        )

        if not header:
            return context

        if len(header) > self._MAX_HEADER_LENGTH:
            _logger.warning(
                "Baggage header `%s` exceeded the maximum number of bytes per baggage-string",
                header,
            )
            return context

        baggage_entries = split(_DELIMITER_PATTERN, header)
        total_baggage_entries = self._MAX_PAIRS

        if len(baggage_entries) > self._MAX_PAIRS:
            _logger.warning(
                "Baggage header `%s` exceeded the maximum number of list-members",
                header,
            )

        for entry in baggage_entries:
            if len(entry) > self._MAX_PAIR_LENGTH:
                _logger.warning(
                    "Baggage entry `%s` exceeded the maximum number of bytes per list-member",
                    entry,
                )
                continue
            if not entry:  # empty string
                continue
            try:
                name, value = entry.split("=", 1)
            except Exception:  # pylint: disable=broad-except
                _logger.warning(
                    "Baggage list-member `%s` doesn't match the format", entry
                )
                continue
            name = unquote_plus(name).strip().lower()
            value = unquote_plus(value).strip()
            if not _is_valid_pair(name, value):
                _logger.warning("Invalid baggage entry: `%s`", entry)
                continue

            context = set_baggage(
                name,
                value,
                context=context,
            )
            total_baggage_entries -= 1
            if total_baggage_entries == 0:
                break

        return context
Exemple #11
0
    def extract(
        self,
        carrier: CarrierT,
        context: typing.Optional[Context] = None,
        getter: Getter = default_getter,
    ) -> Context:
        if context is None:
            context = Context()
        trace_id = trace.INVALID_TRACE_ID
        span_id = trace.INVALID_SPAN_ID
        sampled = "0"
        flags = None

        single_header = _extract_first_element(
            getter.get(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:
            trace_id = (_extract_first_element(
                getter.get(carrier, self.TRACE_ID_KEY)) or trace_id)
            span_id = (_extract_first_element(
                getter.get(carrier, self.SPAN_ID_KEY)) or span_id)
            sampled = (_extract_first_element(
                getter.get(carrier, self.SAMPLED_KEY)) or sampled)
            flags = (_extract_first_element(getter.get(
                carrier, self.FLAGS_KEY)) or flags)

        if (trace_id == trace.INVALID_TRACE_ID
                or span_id == trace.INVALID_SPAN_ID
                or self._trace_id_regex.fullmatch(trace_id) is None
                or self._span_id_regex.fullmatch(span_id) is None):
            return context

        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.NonRecordingSpan(
                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(),
                )),
            context,
        )