def decorated_function(
     exchange: str,
     routing_key: str,
     body: bytes,
     properties: BasicProperties = None,
     mandatory: bool = False,
 ) -> Any:
     if not properties:
         properties = BasicProperties(headers={})
     ctx = context.get_current()
     span = _get_span(
         tracer,
         channel,
         properties,
         span_kind=SpanKind.PRODUCER,
         task_name="(temporary)",
         ctx=ctx,
         operation=None,
     )
     if not span:
         return original_function(
             exchange, routing_key, body, properties, mandatory
         )
     with trace.use_span(span, end_on_exit=True):
         if span.is_recording():
             propagate.inject(properties.headers)
         retval = original_function(
             exchange, routing_key, body, properties, mandatory
         )
     return retval
示例#2
0
    def _instrumented_open_call(_, request, call_wrapped,
                                get_or_create_headers):  # pylint: disable=too-many-locals
        if context.get_value(
                _SUPPRESS_INSTRUMENTATION_KEY) or context.get_value(
                    _SUPPRESS_HTTP_INSTRUMENTATION_KEY):
            return call_wrapped()

        method = request.get_method().upper()
        url = request.full_url

        span_name = f"HTTP {method}".strip()

        url = remove_url_credentials(url)

        labels = {
            SpanAttributes.HTTP_METHOD: method,
            SpanAttributes.HTTP_URL: url,
        }

        with tracer.start_as_current_span(span_name,
                                          kind=SpanKind.CLIENT,
                                          attributes=labels) as span:
            exception = None
            if callable(request_hook):
                request_hook(span, request)

            headers = get_or_create_headers()
            inject(headers)

            token = context.attach(
                context.set_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY, True))
            try:
                result = call_wrapped()  # *** PROCEED
            except Exception as exc:  # pylint: disable=W0703
                exception = exc
                result = getattr(exc, "file", None)
            finally:
                context.detach(token)

            if result is not None:

                code_ = result.getcode()
                labels[SpanAttributes.HTTP_STATUS_CODE] = str(code_)

                if span.is_recording():
                    span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, code_)
                    span.set_status(Status(http_status_to_status_code(code_)))

                ver_ = str(getattr(result, "version", ""))
                if ver_:
                    labels[
                        SpanAttributes.HTTP_FLAVOR] = f"{ver_[:1]}.{ver_[:-1]}"

            if callable(response_hook):
                response_hook(span, request, result)

            if exception is not None:
                raise exception.with_traceback(exception.__traceback__)

        return result
    async def on_request_start(
        unused_session: aiohttp.ClientSession,
        trace_config_ctx: types.SimpleNamespace,
        params: aiohttp.TraceRequestStartParams,
    ):
        if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY):
            trace_config_ctx.span = None
            return

        http_method = params.method.upper()
        request_span_name = f"HTTP {http_method}"
        request_url = (remove_url_credentials(
            trace_config_ctx.url_filter(params.url)) if callable(
                trace_config_ctx.url_filter) else remove_url_credentials(
                    str(params.url)))

        span_attributes = {
            SpanAttributes.HTTP_METHOD: http_method,
            SpanAttributes.HTTP_URL: request_url,
        }

        trace_config_ctx.span = trace_config_ctx.tracer.start_span(
            request_span_name,
            kind=SpanKind.CLIENT,
            attributes=span_attributes)

        if callable(request_hook):
            request_hook(trace_config_ctx.span, params)

        trace_config_ctx.token = context_api.attach(
            trace.set_span_in_context(trace_config_ctx.span))

        inject(params.headers)
    def intercept_stream(self, request_or_iterator, metadata, client_info,
                         invoker):
        if client_info.is_server_stream:
            return self._intercept_server_stream(request_or_iterator, metadata,
                                                 client_info, invoker)

        if not metadata:
            mutable_metadata = OrderedDict()
        else:
            mutable_metadata = OrderedDict(metadata)

        with self._start_guarded_span(client_info.full_method) as guarded_span:
            inject(mutable_metadata, setter=_carrier_setter)
            metadata = tuple(mutable_metadata.items())
            rpc_info = RpcInfo(
                full_method=client_info.full_method,
                metadata=metadata,
                timeout=client_info.timeout,
                request=request_or_iterator,
            )

            rpc_info.request = request_or_iterator

            try:
                result = invoker(request_or_iterator, metadata)
            except grpc.RpcError as err:
                guarded_span.generated_span.set_status(Status(
                    StatusCode.ERROR))
                guarded_span.generated_span.set_attribute(
                    SpanAttributes.RPC_GRPC_STATUS_CODE,
                    err.code().value[0],
                )
                raise err

            return self._trace_result(guarded_span, rpc_info, result)
    def instrumented_urlopen(wrapped, instance, args, kwargs):
        if _is_instrumentation_suppressed():
            return wrapped(*args, **kwargs)

        method = _get_url_open_arg("method", args, kwargs).upper()
        url = _get_url(instance, args, kwargs, url_filter)
        headers = _prepare_headers(kwargs)
        body = _get_url_open_arg("body", args, kwargs)

        span_name = f"HTTP {method.strip()}"
        span_attributes = {
            SpanAttributes.HTTP_METHOD: method,
            SpanAttributes.HTTP_URL: url,
        }

        with tracer.start_as_current_span(
                span_name, kind=SpanKind.CLIENT, attributes=span_attributes
        ) as span, set_ip_on_next_http_connection(span):
            if callable(request_hook):
                request_hook(span, instance, headers, body)
            inject(headers)

            with _suppress_further_instrumentation():
                response = wrapped(*args, **kwargs)

            _apply_response(span, response)
            if callable(response_hook):
                response_hook(span, instance, response)
            return response
    def _trace_before_publish(self, *args, **kwargs):
        task = utils.retrieve_task_from_sender(kwargs)
        task_id = utils.retrieve_task_id_from_message(kwargs)

        if task is None or task_id is None:
            return

        operation_name = f"{_TASK_APPLY_ASYNC}/{task.name}"
        span = self._tracer.start_span(
            operation_name, kind=trace.SpanKind.PRODUCER
        )

        # apply some attributes here because most of the data is not available
        if span.is_recording():
            span.set_attribute(_TASK_TAG_KEY, _TASK_APPLY_ASYNC)
            span.set_attribute(SpanAttributes.MESSAGING_MESSAGE_ID, task_id)
            span.set_attribute(_TASK_NAME_KEY, task.name)
            utils.set_attributes_from_context(span, kwargs)

        activation = trace.use_span(span, end_on_exit=True)
        activation.__enter__()  # pylint: disable=E1101

        utils.attach_span(task, task_id, (span, activation), is_publish=True)

        headers = kwargs.get("headers")
        if headers:
            inject(headers)
示例#7
0
    def intercept_unary(self, request, metadata, client_info, invoker):
        if not metadata:
            mutable_metadata = OrderedDict()
        else:
            mutable_metadata = OrderedDict(metadata)

        with self._start_guarded_span(client_info.full_method) as guarded_span:
            inject(mutable_metadata, setter=_carrier_setter)
            metadata = tuple(mutable_metadata.items())

            rpc_info = RpcInfo(
                full_method=client_info.full_method,
                metadata=metadata,
                timeout=client_info.timeout,
                request=request,
            )

            try:
                result = invoker(request, metadata)
            except grpc.RpcError as err:
                guarded_span.generated_span.set_status(Status(
                    StatusCode.ERROR))
                guarded_span.generated_span.set_attribute(
                    "rpc.grpc.status_code",
                    err.code().value[0])
                raise err

            return self._trace_result(guarded_span, rpc_info, result)
示例#8
0
    def before_enqueue(self, _broker, message, delay):
        retry_count = message.options.get("retries", 0)
        operation_name = utils.get_operation_name("before_enqueue",
                                                  retry_count)
        span_attributes = {_REMOULADE_MESSAGE_RETRY_COUNT_KEY: retry_count}

        span = self._tracer.start_span(
            operation_name,
            kind=trace.SpanKind.PRODUCER,
            attributes=span_attributes,
        )

        if span.is_recording():
            span.set_attributes({
                _REMOULADE_MESSAGE_TAG_KEY:
                _REMOULADE_MESSAGE_SEND,
                _REMOULADE_MESSAGE_NAME_KEY:
                message.actor_name,
                SpanAttributes.MESSAGING_MESSAGE_ID:
                message.message_id,
            })

        activation = trace.use_span(span, end_on_exit=True)
        activation.__enter__()  # pylint: disable=E1101

        utils.attach_span(
            self._span_registry,
            message.message_id,
            (span, activation),
            is_publish=True,
        )

        if "trace_ctx" not in message.options:
            message.options["trace_ctx"] = {}
        inject(message.options["trace_ctx"])
 def decorated_function(
     exchange: str,
     routing_key: str,
     body: bytes,
     properties: BasicProperties = None,
     mandatory: bool = False,
 ) -> Any:
     if not properties:
         properties = BasicProperties(headers={})
     if properties.headers is None:
         properties.headers = {}
     span = _get_span(
         tracer,
         channel,
         properties,
         destination=exchange if exchange else routing_key,
         span_kind=SpanKind.PRODUCER,
         task_name="(temporary)",
         operation=None,
     )
     if not span:
         return original_function(exchange, routing_key, body, properties,
                                  mandatory)
     with trace.use_span(span, end_on_exit=True):
         if span.is_recording():
             propagate.inject(properties.headers)
             try:
                 publish_hook(span, body, properties)
             except Exception as hook_exception:  # pylint: disable=W0703
                 _LOG.exception(hook_exception)
         retval = original_function(exchange, routing_key, body, properties,
                                    mandatory)
     return retval
示例#10
0
    def instrumented_urlopen(wrapped, instance, args, kwargs):
        if _is_instrumentation_suppressed():
            return wrapped(*args, **kwargs)

        method = _get_url_open_arg("method", args, kwargs).upper()
        url = _get_url(instance, args, kwargs, url_filter)
        headers = _prepare_headers(kwargs)

        span_name = _get_span_name(span_name_or_callback, method, url, headers)
        span_attributes = {
            "http.method": method,
            "http.url": url,
        }

        with get_tracer(__name__, __version__,
                        tracer_provider).start_as_current_span(
                            span_name,
                            kind=SpanKind.CLIENT,
                            attributes=span_attributes) as span:
            inject(headers)

            with _suppress_further_instrumentation():
                response = wrapped(*args, **kwargs)

            _apply_response(span, response)
            return response
示例#11
0
    def test_propagation(self):
        traceparent_value = "00-{trace_id}-{span_id}-00".format(
            trace_id=format(self.TRACE_ID, "032x"),
            span_id=format(self.SPAN_ID, "016x"),
        )
        tracestate_value = "foo=1,bar=2,baz=3"
        headers = {
            "baggage": ["key1=val1,key2=val2"],
            "traceparent": [traceparent_value],
            "tracestate": [tracestate_value],
        }
        ctx = extract(carrier_getter, headers)
        baggage_entries = baggage.get_all(context=ctx)
        expected = {"key1": "val1", "key2": "val2"}
        self.assertEqual(baggage_entries, expected)
        span_context = get_current_span(context=ctx).get_span_context()

        self.assertEqual(span_context.trace_id, self.TRACE_ID)
        self.assertEqual(span_context.span_id, self.SPAN_ID)

        span = trace.NonRecordingSpan(span_context)
        ctx = baggage.set_baggage("key3", "val3")
        ctx = baggage.set_baggage("key4", "val4", context=ctx)
        ctx = set_span_in_context(span, context=ctx)
        output = {}
        inject(dict.__setitem__, output, context=ctx)
        self.assertEqual(traceparent_value, output["traceparent"])
        self.assertIn("key3=val3", output["baggage"])
        self.assertIn("key4=val4", output["baggage"])
        self.assertIn("foo=1", output["tracestate"])
        self.assertIn("bar=2", output["tracestate"])
        self.assertIn("baz=3", output["tracestate"])
示例#12
0
    def _traced_send(func, instance, args, kwargs):
        headers = KafkaPropertiesExtractor.extract_send_headers(args, kwargs)
        if headers is None:
            headers = []
            kwargs["headers"] = headers

        topic = KafkaPropertiesExtractor.extract_send_topic(args)
        bootstrap_servers = KafkaPropertiesExtractor.extract_bootstrap_servers(
            instance)
        partition = KafkaPropertiesExtractor.extract_send_partition(
            instance, args, kwargs)
        span_name = _get_span_name("send", topic)
        with tracer.start_as_current_span(
                span_name, kind=trace.SpanKind.PRODUCER) as span:
            _enrich_span(span, bootstrap_servers, topic, partition)
            propagate.inject(
                headers,
                context=trace.set_span_in_context(span),
                setter=_kafka_setter,
            )
            try:
                if callable(produce_hook):
                    produce_hook(span, args, kwargs)
            except Exception as hook_exception:  # pylint: disable=W0703
                _LOG.exception(hook_exception)

        return func(*args, **kwargs)
示例#13
0
    def _intercept_server_stream(self, request_or_iterator, metadata,
                                 client_info, invoker):
        if not metadata:
            mutable_metadata = OrderedDict()
        else:
            mutable_metadata = OrderedDict(metadata)

        with self._start_span(client_info.full_method) as span:
            inject(mutable_metadata, setter=_carrier_setter)
            metadata = tuple(mutable_metadata.items())
            rpc_info = RpcInfo(
                full_method=client_info.full_method,
                metadata=metadata,
                timeout=client_info.timeout,
            )

            if client_info.is_client_stream:
                rpc_info.request = request_or_iterator

            try:
                yield from invoker(request_or_iterator, metadata)
            except grpc.RpcError as err:
                span.set_status(Status(StatusCode.ERROR))
                span.set_attribute(SpanAttributes.RPC_GRPC_STATUS_CODE,
                                   err.code().value[0])
                raise err
示例#14
0
    def wrap_produce(func, instance, tracer, args, kwargs):
        topic = kwargs.get("topic")
        if not topic:
            topic = args[0]

        span_name = _get_span_name("send", topic)
        with tracer.start_as_current_span(
            name=span_name, kind=trace.SpanKind.PRODUCER
        ) as span:
            headers = KafkaPropertiesExtractor.extract_produce_headers(
                args, kwargs
            )
            if headers is None:
                headers = []
                kwargs["headers"] = headers

            topic = KafkaPropertiesExtractor.extract_produce_topic(args)
            _enrich_span(
                span,
                topic,
                operation=MessagingOperationValues.RECEIVE,
            )  # Replace
            propagate.inject(
                headers,
                setter=_kafka_setter,
            )
            return func(*args, **kwargs)
示例#15
0
def fetch_async(tracer, func, _, args, kwargs):
    start_time = time_ns()

    # Return immediately if no args were provided (error)
    # or original_request is set (meaning we are in a redirect step).
    if len(args) == 0 or hasattr(args[0], "original_request"):
        return func(*args, **kwargs)

    # Force the creation of a HTTPRequest object if needed,
    # so we can inject the context into the headers.
    args, kwargs = _normalize_request(args, kwargs)
    request = args[0]

    span = tracer.start_span(
        request.method,
        kind=trace.SpanKind.CLIENT,
        start_time=start_time,
    )

    if span.is_recording():
        attributes = {
            "http.url": request.url,
            "http.method": request.method,
        }
        for key, value in attributes.items():
            span.set_attribute(key, value)

    with tracer.use_span(span):
        inject(type(request.headers).__setitem__, request.headers)
        future = func(*args, **kwargs)
        future.add_done_callback(
            functools.partial(_finish_tracing_callback, span=span))
        return future
    def _instrumented_requests_call(method: str, url: str, call_wrapped,
                                    get_or_create_headers):
        if context.get_value("suppress_instrumentation") or context.get_value(
                _SUPPRESS_REQUESTS_INSTRUMENTATION_KEY):
            return call_wrapped()

        # See
        # https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-client
        method = method.upper()
        span_name = ""
        if name_callback is not None:
            span_name = name_callback(method, url)
        if not span_name or not isinstance(span_name, str):
            span_name = get_default_span_name(method)

        labels = {}
        labels["http.method"] = method
        labels["http.url"] = url

        with get_tracer(__name__, __version__,
                        tracer_provider).start_as_current_span(
                            span_name, kind=SpanKind.CLIENT) as span:
            exception = None
            if span.is_recording():
                span.set_attribute("http.method", method)
                span.set_attribute("http.url", url)

            headers = get_or_create_headers()
            inject(type(headers).__setitem__, headers)

            token = context.attach(
                context.set_value(_SUPPRESS_REQUESTS_INSTRUMENTATION_KEY,
                                  True))
            try:
                result = call_wrapped()  # *** PROCEED
            except Exception as exc:  # pylint: disable=W0703
                exception = exc
                result = getattr(exc, "response", None)
            finally:
                context.detach(token)

            if isinstance(result, Response):
                if span.is_recording():
                    span.set_attribute("http.status_code", result.status_code)
                    span.set_attribute("http.status_text", result.reason)
                    span.set_status(
                        Status(http_status_to_status_code(result.status_code)))
                labels["http.status_code"] = str(result.status_code)
                if result.raw and result.raw.version:
                    labels["http.flavor"] = (str(result.raw.version)[:1] +
                                             "." +
                                             str(result.raw.version)[:-1])
            if span_callback is not None:
                span_callback(span, result)

            if exception is not None:
                raise exception.with_traceback(exception.__traceback__)

        return result
示例#17
0
def _inject_propagation_headers(headers, args, kwargs):
    _headers = _prepare_headers(headers)
    inject(_headers)
    if isinstance(args[0], httpx.Request):
        request: httpx.Request = args[0]
        request.headers = _headers
    else:
        kwargs["headers"] = _headers.raw
示例#18
0
def _inject_span_context(metadata: MutableMapping[str, str]) -> None:
    # pylint:disable=unused-argument
    def append_metadata(carrier: MutableMapping[str, str], key: str,
                        value: str):
        metadata[key] = value

    # Inject current active span from the context
    inject(append_metadata, metadata)
示例#19
0
 def to_header(self):  # pylint: disable=no-self-use
     # type: () -> Dict[str, str]
     """
     Returns a dictionary with the header labels and values.
     :return: A key value pair dictionary
     """
     temp_headers = {}  # type: Dict[str, str]
     inject(temp_headers)
     return temp_headers
示例#20
0
    def _instrumented_requests_call(
        method: str, url: str, call_wrapped, get_or_create_headers
    ):
        if context.get_value(
            _SUPPRESS_INSTRUMENTATION_KEY
        ) or context.get_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY):
            return call_wrapped()

        # See
        # https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-client
        method = method.upper()
        span_name = ""
        if name_callback is not None:
            span_name = name_callback(method, url)
        if not span_name or not isinstance(span_name, str):
            span_name = get_default_span_name(method)

        url = remove_url_credentials(url)

        with tracer.start_as_current_span(
            span_name, kind=SpanKind.CLIENT
        ) as span:
            exception = None
            if span.is_recording():
                span.set_attribute(SpanAttributes.HTTP_METHOD, method)
                span.set_attribute(SpanAttributes.HTTP_URL, url)

            headers = get_or_create_headers()
            inject(headers)

            token = context.attach(
                context.set_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY, True)
            )
            try:
                result = call_wrapped()  # *** PROCEED
            except Exception as exc:  # pylint: disable=W0703
                exception = exc
                result = getattr(exc, "response", None)
            finally:
                context.detach(token)

            if isinstance(result, Response):
                if span.is_recording():
                    span.set_attribute(
                        SpanAttributes.HTTP_STATUS_CODE, result.status_code
                    )
                    span.set_status(
                        Status(http_status_to_status_code(result.status_code))
                    )
            if span_callback is not None:
                span_callback(span, result)

            if exception is not None:
                raise exception.with_traceback(exception.__traceback__)

        return result
示例#21
0
    async def handle_async_request(
        self,
        method: bytes,
        url: URL,
        headers: typing.Optional[Headers] = None,
        stream: typing.Optional[httpx.AsyncByteStream] = None,
        extensions: typing.Optional[dict] = None,
    ) -> typing.Tuple[int, "Headers", httpx.AsyncByteStream, dict]:
        """Add request info to span."""
        if context.get_value("suppress_instrumentation"):
            return await self._transport.handle_async_request(
                method,
                url,
                headers=headers,
                stream=stream,
                extensions=extensions,
            )

        span_attributes = _prepare_attributes(method, url)
        _headers = _prepare_headers(headers)
        span_name = _get_default_span_name(
            span_attributes[SpanAttributes.HTTP_METHOD]
        )
        request = RequestInfo(method, url, headers, stream, extensions)

        with self._tracer.start_as_current_span(
            span_name, kind=SpanKind.CLIENT, attributes=span_attributes
        ) as span:
            if self._request_hook is not None:
                await self._request_hook(span, request)

            inject(_headers)

            (
                status_code,
                headers,
                stream,
                extensions,
            ) = await self._transport.handle_async_request(
                method,
                url,
                headers=_headers.raw,
                stream=stream,
                extensions=extensions,
            )

            _apply_status_code(span, status_code)

            if self._response_hook is not None:
                await self._response_hook(
                    span,
                    request,
                    ResponseInfo(status_code, headers, stream, extensions),
                )

        return status_code, headers, stream, extensions
 def _patch_lambda_invoke(api_params):
     try:
         payload_str = api_params["Payload"]
         payload = json.loads(payload_str)
         headers = payload.get("headers", {})
         inject(headers)
         payload["headers"] = headers
         api_params["Payload"] = json.dumps(payload)
     except ValueError:
         pass
示例#23
0
 async def decorated_publish(
         message: AbstractMessage, routing_key: str,
         **kwargs) -> Optional[aiormq.abc.ConfirmationFrameType]:
     span = self._get_publish_span(message, routing_key)
     if not span:
         return await publish(message, routing_key, **kwargs)
     with trace.use_span(span, end_on_exit=True):
         if span.is_recording():
             propagate.inject(message.properties.headers)
         return_value = await publish(message, routing_key, **kwargs)
     return return_value
    def _inject_current_span(cls, call_context: _AwsSdkCallContext):
        payload_str = call_context.params.get("Payload")
        if payload_str is None:
            return

        # TODO: reconsider propagation via payload as it manipulates input of the called lambda function
        try:
            payload = json.loads(payload_str)
            headers = payload.get("headers", {})
            inject(headers)
            payload["headers"] = headers
            call_context.params["Payload"] = json.dumps(payload)
        except ValueError:
            pass
示例#25
0
    def _intercept(self, request, metadata, client_info, invoker):
        if context.get_value(_SUPPRESS_INSTRUMENTATION_KEY):
            return invoker(request, metadata)

        if not metadata:
            mutable_metadata = OrderedDict()
        else:
            mutable_metadata = OrderedDict(metadata)
        with self._start_span(
                client_info.full_method,
                end_on_exit=False,
                record_exception=False,
                set_status_on_exception=False,
        ) as span:
            result = None
            try:
                inject(mutable_metadata, setter=_carrier_setter)
                metadata = tuple(mutable_metadata.items())

                rpc_info = RpcInfo(
                    full_method=client_info.full_method,
                    metadata=metadata,
                    timeout=client_info.timeout,
                    request=request,
                )

                result = invoker(request, metadata)
            except Exception as exc:
                if isinstance(exc, grpc.RpcError):
                    span.set_attribute(
                        SpanAttributes.RPC_GRPC_STATUS_CODE,
                        exc.code().value[0],
                    )
                span.set_status(
                    Status(
                        status_code=StatusCode.ERROR,
                        description=f"{type(exc).__name__}: {exc}",
                    ))
                span.record_exception(exc)
                raise exc
            finally:
                if not result:
                    span.end()
        return self._trace_result(span, rpc_info, result)
示例#26
0
    def instrumented_urlopen(wrapped, instance, args, kwargs):
        if _is_instrumentation_suppressed():
            return wrapped(*args, **kwargs)

        method = _get_url_open_arg("method", args, kwargs).upper()
        url = _get_url(instance, args, kwargs, url_filter)
        headers = _prepare_headers(kwargs)
        body = _get_url_open_arg("body", args, kwargs)

        span_name = f"HTTP {method.strip()}"
        span_attributes = {
            SpanAttributes.HTTP_METHOD: method,
            SpanAttributes.HTTP_URL: url,
        }

        with tracer.start_as_current_span(
                span_name, kind=SpanKind.CLIENT, attributes=span_attributes
        ) as span, set_ip_on_next_http_connection(span):
            if callable(request_hook):
                request_hook(span, instance, headers, body)
            inject(headers)

            with _suppress_further_instrumentation():
                start_time = default_timer()
                response = wrapped(*args, **kwargs)
                elapsed_time = round((default_timer() - start_time) * 1000)

            _apply_response(span, response)
            if callable(response_hook):
                response_hook(span, instance, response)

            request_size = 0 if body is None else len(body)
            response_size = int(response.headers.get("Content-Length", 0))
            metric_attributes = _create_metric_attributes(
                instance, response, method)

            duration_histogram.record(elapsed_time,
                                      attributes=metric_attributes)
            request_size_histogram.record(request_size,
                                          attributes=metric_attributes)
            response_size_histogram.record(response_size,
                                           attributes=metric_attributes)

            return response
 def send_batch_wrapper(wrapped, instance, args, kwargs):
     queue_url = kwargs.get("QueueUrl")
     entries = kwargs.get("Entries")
     # The method expect QueueUrl and Entries params, so if they are None, we call wrapped to receive the
     # original exception
     if (context.get_value(_SUPPRESS_INSTRUMENTATION_KEY)
             or not queue_url or not entries):
         return wrapped(*args, **kwargs)
     queue_name = Boto3SQSInstrumentor._extract_queue_name_from_url(
         queue_url)
     ids_to_spans: Dict[str, Span] = {}
     for entry in entries:
         entry_id = entry["Id"]
         span = self._tracer.start_span(name=f"{queue_name} send",
                                        kind=SpanKind.PRODUCER)
         ids_to_spans[entry_id] = span
         Boto3SQSInstrumentor._enrich_span(span,
                                           queue_name,
                                           queue_url,
                                           conversation_id=entry_id)
         with trace.use_span(span):
             if "MessageAttributes" not in entry:
                 entry["MessageAttributes"] = {}
             propagate.inject(entry["MessageAttributes"],
                              setter=boto3sqs_setter)
     retval = wrapped(*args, **kwargs)
     for successful_messages in retval["Successful"]:
         message_identifier = successful_messages["Id"]
         message_span = ids_to_spans.get(message_identifier)
         if message_span:
             if message_span.is_recording():
                 message_span.set_attribute(
                     SpanAttributes.MESSAGING_MESSAGE_ID,
                     successful_messages.get("MessageId"),
                 )
     for span in ids_to_spans.values():
         span.end()
     return retval
    async def on_request_start(
        unused_session: aiohttp.ClientSession,
        trace_config_ctx: types.SimpleNamespace,
        params: aiohttp.TraceRequestStartParams,
    ):
        if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY):
            trace_config_ctx.span = None
            return

        http_method = params.method.upper()
        if trace_config_ctx.span_name is None:
            request_span_name = "HTTP {}".format(http_method)
        elif callable(trace_config_ctx.span_name):
            request_span_name = str(trace_config_ctx.span_name(params))
        else:
            request_span_name = str(trace_config_ctx.span_name)

        trace_config_ctx.span = trace_config_ctx.tracer.start_span(
            request_span_name,
            kind=SpanKind.CLIENT,
        )

        if trace_config_ctx.span.is_recording():
            attributes = {
                SpanAttributes.HTTP_METHOD:
                http_method,
                SpanAttributes.HTTP_URL:
                remove_url_credentials(trace_config_ctx.url_filter(params.url))
                if callable(trace_config_ctx.url_filter) else
                remove_url_credentials(str(params.url)),
            }
            for key, value in attributes.items():
                trace_config_ctx.span.set_attribute(key, value)

        trace_config_ctx.token = context_api.attach(
            trace.set_span_in_context(trace_config_ctx.span))

        inject(params.headers)
 def send_wrapper(wrapped, instance, args, kwargs):
     if context.get_value(_SUPPRESS_INSTRUMENTATION_KEY):
         return wrapped(*args, **kwargs)
     queue_url = kwargs.get("QueueUrl")
     # The method expect QueueUrl and Entries params, so if they are None, we call wrapped to receive the
     # original exception
     queue_name = Boto3SQSInstrumentor._extract_queue_name_from_url(
         queue_url)
     with self._tracer.start_as_current_span(
             name=f"{queue_name} send",
             kind=SpanKind.PRODUCER,
             end_on_exit=True,
     ) as span:
         Boto3SQSInstrumentor._enrich_span(span, queue_name, queue_url)
         attributes = kwargs.pop("MessageAttributes", {})
         propagate.inject(attributes, setter=boto3sqs_setter)
         retval = wrapped(*args, MessageAttributes=attributes, **kwargs)
         message_id = retval.get("MessageId")
         if message_id:
             if span.is_recording():
                 span.set_attribute(SpanAttributes.MESSAGING_MESSAGE_ID,
                                    message_id)
         return retval
    async def on_request_start(
        unused_session: aiohttp.ClientSession,
        trace_config_ctx: types.SimpleNamespace,
        params: aiohttp.TraceRequestStartParams,
    ):
        if context_api.get_value("suppress_instrumentation"):
            trace_config_ctx.span = None
            return

        http_method = params.method.upper()
        if trace_config_ctx.span_name is None:
            request_span_name = "HTTP {}".format(http_method)
        elif callable(trace_config_ctx.span_name):
            request_span_name = str(trace_config_ctx.span_name(params))
        else:
            request_span_name = str(trace_config_ctx.span_name)

        trace_config_ctx.span = trace_config_ctx.tracer.start_span(
            request_span_name,
            kind=SpanKind.CLIENT,
        )

        if trace_config_ctx.span.is_recording():
            attributes = {
                "http.method":
                http_method,
                "http.url":
                trace_config_ctx.url_filter(params.url)
                if callable(trace_config_ctx.url_filter) else str(params.url),
            }
            for key, value in attributes.items():
                trace_config_ctx.span.set_attribute(key, value)

        trace_config_ctx.token = context_api.attach(
            trace.set_span_in_context(trace_config_ctx.span))

        inject(type(params.headers).__setitem__, params.headers)