Beispiel #1
0
 def test_with_nested_nonrecording_span(self):
     tracer = trace.get_tracer(__name__)
     with tracer.start_as_current_span(
         "requests HTTP GET"
     ) as span, set_ip_on_next_http_connection(span):
         with trace.use_span(INVALID_SPAN), set_ip_on_next_http_connection(
             INVALID_SPAN
         ):
             resp, body = self.perform_request()
     assert resp.status == 200
     assert body == b"Hello!"
     span = self.assert_span(num_spans=1)
     self.assertEqual(span.attributes, {"net.peer.ip": "127.0.0.1"})
Beispiel #2
0
 def test_with_nested_span(self):
     tracer = trace.get_tracer(__name__)
     with tracer.start_as_current_span(
         "requests HTTP GET"
     ) as span, set_ip_on_next_http_connection(span):
         with tracer.start_as_current_span(
             "urllib3 HTTP GET"
         ) as span2, set_ip_on_next_http_connection(span2):
             resp, body = self.perform_request()
     assert resp.status == 200
     assert body == b"Hello!"
     for span in self.assert_span(num_spans=2):
         self.assertEqual(span.attributes, {"net.peer.ip": "127.0.0.1"})
    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
Beispiel #4
0
 def test_with_only_nonrecording_span(self):
     with trace.use_span(INVALID_SPAN), set_ip_on_next_http_connection(
         INVALID_SPAN
     ):
         resp, body = self.perform_request()
     assert resp.status == 200
     assert body == b"Hello!"
     self.assert_span(num_spans=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, set_ip_on_next_http_connection(
                    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
Beispiel #6
0
    def test_uninstrument(self):
        HttpClientInstrumentor().uninstrument()

        tracer = trace.get_tracer(__name__)
        with tracer.start_as_current_span(
            "HTTP GET"
        ) as span, set_ip_on_next_http_connection(span):
            body = self.perform_request()[1]
        self.assertEqual(b"Hello!", body)

        # We should have a span, but it should have no attributes
        self.assertFalse(self.assert_span(num_spans=1).attributes)

        # instrument again to avoid warning message on tearDown
        HttpClientInstrumentor().instrument()
Beispiel #7
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 _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)

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

        metric_labels = {
            SpanAttributes.HTTP_METHOD: method,
        }

        try:
            parsed_url = urlparse(url)
            metric_labels[SpanAttributes.HTTP_SCHEME] = parsed_url.scheme
            if parsed_url.hostname:
                metric_labels[SpanAttributes.HTTP_HOST] = parsed_url.hostname
                metric_labels[
                    SpanAttributes.NET_PEER_NAME] = parsed_url.hostname
            if parsed_url.port:
                metric_labels[SpanAttributes.NET_PEER_PORT] = parsed_url.port
        except ValueError:
            pass

        with tracer.start_as_current_span(
                span_name, kind=SpanKind.CLIENT, attributes=span_attributes
        ) as span, set_ip_on_next_http_connection(span):
            exception = None

            headers = get_or_create_headers()
            inject(headers)

            token = context.attach(
                context.set_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY, True))

            start_time = default_timer()

            try:
                result = call_wrapped()  # *** PROCEED
            except Exception as exc:  # pylint: disable=W0703
                exception = exc
                result = getattr(exc, "response", None)
            finally:
                elapsed_time = max(
                    round((default_timer() - start_time) * 1000), 0)
                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)))

                metric_labels[
                    SpanAttributes.HTTP_STATUS_CODE] = result.status_code

                if result.raw is not None:
                    version = getattr(result.raw, "version", None)
                    if version:
                        metric_labels[SpanAttributes.HTTP_FLAVOR] = (
                            "1.1" if version == 11 else "1.0")

            if span_callback is not None:
                span_callback(span, result)

            duration_histogram.record(elapsed_time, attributes=metric_labels)

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

        return result