Exemplo n.º 1
0
        def _start_response(status, response_headers, *args, **kwargs):
            if flask.request and (
                    excluded_urls is None
                    or not excluded_urls.url_disabled(flask.request.url)):
                span = flask.request.environ.get(_ENVIRON_SPAN_KEY)

                propagator = get_global_response_propagator()
                if propagator:
                    propagator.inject(
                        response_headers,
                        setter=otel_wsgi.default_response_propagation_setter,
                    )

                if span:
                    otel_wsgi.add_response_attributes(span, status,
                                                      response_headers)
                else:
                    _logger.warning(
                        "Flask environ's OpenTelemetry span "
                        "missing at _start_response(%s)",
                        status,
                    )
                if response_hook is not None:
                    response_hook(span, status, response_headers)
            return start_response(status, response_headers, *args, **kwargs)
 def _start_response(status, response_headers, *args, **kwargs):
     otel_wsgi.add_response_attributes(span, status, response_headers)
     response = start_response(status, response_headers, *args,
                               **kwargs)
     activation.__exit__(None, None, None)
     context.detach(token)
     return response
    def process_response(self, request, response):
        if self._excluded_urls.url_disabled(request.build_absolute_uri("?")):
            return response

        if (self._environ_activation_key in request.META.keys()
                and self._environ_span_key in request.META.keys()):
            add_response_attributes(
                request.META[self._environ_span_key],
                "{} {}".format(response.status_code, response.reason_phrase),
                response,
            )

            request.META.pop(self._environ_span_key)

            exception = request.META.pop(self._environ_exception_key, None)
            if exception:
                request.META[self._environ_activation_key].__exit__(
                    type(exception),
                    exception,
                    getattr(exception, "__traceback__", None),
                )
            else:
                request.META[self._environ_activation_key].__exit__(
                    None, None, None)
            request.META.pop(self._environ_activation_key)

        if self._environ_token in request.META.keys():
            detach(request.environ.get(self._environ_token))
            request.META.pop(self._environ_token)

        return response
Exemplo n.º 4
0
        def _start_response(status, response_headers, *args, **kwargs):
            if flask.request and (
                    excluded_urls is None
                    or not excluded_urls.url_disabled(flask.request.url)):
                span = flask.request.environ.get(_ENVIRON_SPAN_KEY)

                propagator = get_global_response_propagator()
                if propagator:
                    propagator.inject(
                        response_headers,
                        setter=otel_wsgi.default_response_propagation_setter,
                    )

                if span:
                    otel_wsgi.add_response_attributes(span, status,
                                                      response_headers)
                    status_code = otel_wsgi._parse_status_code(status)
                    if status_code is not None:
                        duration_attrs[
                            SpanAttributes.HTTP_STATUS_CODE] = status_code
                    if (span.is_recording()
                            and span.kind == trace.SpanKind.SERVER):
                        custom_attributes = otel_wsgi.collect_custom_response_headers_attributes(
                            response_headers)
                        if len(custom_attributes) > 0:
                            span.set_attributes(custom_attributes)
                else:
                    _logger.warning(
                        "Flask environ's OpenTelemetry span "
                        "missing at _start_response(%s)",
                        status,
                    )
                if response_hook is not None:
                    response_hook(span, status, response_headers)
            return start_response(status, response_headers, *args, **kwargs)
    def process_response(self, request, response):
        if self._excluded_urls.url_disabled(request.build_absolute_uri("?")):
            return response

        activation = request.META.pop(self._environ_activation_key, None)
        span = request.META.pop(self._environ_span_key, None)

        if activation and span:
            add_response_attributes(
                span,
                "{} {}".format(response.status_code, response.reason_phrase),
                response,
            )

            exception = request.META.pop(self._environ_exception_key, None)
            if _DjangoMiddleware._otel_response_hook:
                _DjangoMiddleware._otel_response_hook(  # pylint: disable=not-callable
                    span, request, response
                )

            if exception:
                activation.__exit__(
                    type(exception),
                    exception,
                    getattr(exception, "__traceback__", None),
                )
            else:
                activation.__exit__(None, None, None)

        if self._environ_token in request.META.keys():
            detach(request.environ.get(self._environ_token))
            request.META.pop(self._environ_token)

        return response
    def process_response(self, request, response):
        if self._excluded_urls.url_disabled(request.build_absolute_uri("?")):
            return response

        if (self._environ_activation_key in request.META.keys()
                and self._environ_span_key in request.META.keys()):
            add_response_attributes(
                request.META[self._environ_span_key],
                "{} {}".format(response.status_code, response.reason_phrase),
                response,
            )
            # pylint:disable=W0212
            request._otel_labels["http.status_code"] = str(
                response.status_code)
            request.META.pop(self._environ_span_key)

            request.META[self._environ_activation_key].__exit__(
                None, None, None)
            request.META.pop(self._environ_activation_key)

        if self._environ_token in request.META.keys():
            detach(request.environ.get(self._environ_token))
            request.META.pop(self._environ_token)

        try:
            metric_recorder = getattr(settings, "OTEL_METRIC_RECORDER", None)
            if metric_recorder is not None:
                # pylint:disable=W0212
                metric_recorder.record_server_duration_range(
                    request._otel_start_time, time.time(),
                    request._otel_labels)
        except Exception as ex:  # pylint: disable=W0703
            _logger.warning("Error recording duration metrics: %s", ex)

        return response
Exemplo n.º 7
0
 def test_response_attributes(self):
     otel_wsgi.add_response_attributes(self.span, "404 Not Found", {})
     expected = (
         mock.call("http.status_code", 404),
         mock.call("http.status_text", "Not Found"),
     )
     self.assertEqual(self.span.set_attribute.call_count, len(expected))
     self.span.set_attribute.assert_has_calls(expected, any_order=True)
    def trace_tween(request):
        # pylint: disable=E1101
        if _excluded_urls.url_disabled(request.url):
            request.environ[_ENVIRON_ENABLED_KEY] = False
            # short-circuit when we don't want to trace anything
            return handler(request)

        request.environ[_ENVIRON_ENABLED_KEY] = True
        request.environ[_ENVIRON_STARTTIME_KEY] = _time_ns()

        try:
            response = handler(request)
            response_or_exception = response
        except HTTPException as exc:
            # If the exception is a pyramid HTTPException,
            # that's still valuable information that isn't necessarily
            # a 500. For instance, HTTPFound is a 302.
            # As described in docs, Pyramid exceptions are all valid
            # response types
            response_or_exception = exc
            raise
        finally:
            span = request.environ.get(_ENVIRON_SPAN_KEY)
            enabled = request.environ.get(_ENVIRON_ENABLED_KEY)
            if not span and enabled:
                _logger.warning(
                    "Pyramid environ's OpenTelemetry span missing."
                    "If the OpenTelemetry tween was added manually, make sure"
                    "PyramidInstrumentor().instrument_config(config) is called"
                )
            elif enabled:
                otel_wsgi.add_response_attributes(
                    span,
                    response_or_exception.status,
                    response_or_exception.headers,
                )

                propagator = get_global_response_propagator()
                if propagator:
                    propagator.inject(response.headers)

                activation = request.environ.get(_ENVIRON_ACTIVATION_KEY)

                if isinstance(response_or_exception, HTTPException):
                    activation.__exit__(
                        type(response_or_exception),
                        response_or_exception,
                        getattr(response_or_exception, "__traceback__", None),
                    )
                else:
                    activation.__exit__(None, None, None)

                context.detach(request.environ.get(_ENVIRON_TOKEN))

        return response
Exemplo n.º 9
0
        def _start_response(status, response_headers, *args, **kwargs):
            if not _excluded_urls.url_disabled(flask.request.url):
                span = flask.request.environ.get(_ENVIRON_SPAN_KEY)

                if span:
                    otel_wsgi.add_response_attributes(span, status,
                                                      response_headers)
                else:
                    _logger.warning(
                        "Flask environ's OpenTelemetry span "
                        "missing at _start_response(%s)",
                        status,
                    )

            return start_response(status, response_headers, *args, **kwargs)
    def process_response(self, request, response):
        if self._excluded_urls.url_disabled(request.build_absolute_uri("?")):
            return response

        is_asgi_request = _is_asgi_request(request)
        if not _is_asgi_supported and is_asgi_request:
            return response

        activation = request.META.pop(self._environ_activation_key, None)
        span = request.META.pop(self._environ_span_key, None)

        if activation and span:
            if is_asgi_request:
                set_status_code(span, response.status_code)
            else:
                add_response_attributes(
                    span,
                    f"{response.status_code} {response.reason_phrase}",
                    response,
                )

            propagator = get_global_response_propagator()
            if propagator:
                propagator.inject(response)

            # record any exceptions raised while processing the request
            exception = request.META.pop(self._environ_exception_key, None)
            if _DjangoMiddleware._otel_response_hook:
                _DjangoMiddleware._otel_response_hook(  # pylint: disable=not-callable
                    span, request, response
                )

            if exception:
                activation.__exit__(
                    type(exception),
                    exception,
                    getattr(exception, "__traceback__", None),
                )
            else:
                activation.__exit__(None, None, None)

        if request.META.get(self._environ_token, None) is not None:
            detach(request.META.get(self._environ_token))
            request.META.pop(self._environ_token)

        return response
Exemplo n.º 11
0
 def test_response_attributes_invalid_status_code(self):
     otel_wsgi.add_response_attributes(self.span, "Invalid Status Code", {})
     self.assertEqual(self.span.set_attribute.call_count, 1)
     self.span.set_attribute.assert_called_with(
         "http.status_text", "Status Code"
     )
 def test_response_attributes(self):
     otel_wsgi.add_response_attributes(self.span, "404 Not Found", {})
     expected = (mock.call(SpanAttributes.HTTP_STATUS_CODE, 404),)
     self.assertEqual(self.span.set_attribute.call_count, len(expected))
     self.span.set_attribute.assert_has_calls(expected, any_order=True)
    def trace_tween(request):
        # pylint: disable=E1101
        if _excluded_urls.url_disabled(request.url):
            request.environ[_ENVIRON_ENABLED_KEY] = False
            # short-circuit when we don't want to trace anything
            return handler(request)

        request.environ[_ENVIRON_ENABLED_KEY] = True
        request.environ[_ENVIRON_STARTTIME_KEY] = _time_ns()

        response = None
        status = None

        try:
            response = handler(request)
        except HTTPException as exc:
            # If the exception is a pyramid HTTPException,
            # that's still valuable information that isn't necessarily
            # a 500. For instance, HTTPFound is a 302.
            # As described in docs, Pyramid exceptions are all valid
            # response types
            response = exc
            raise
        except BaseException:
            # In the case that a non-HTTPException is bubbled up we
            # should infer a internal server error and raise
            status = "500 InternalServerError"
            raise
        finally:
            span = request.environ.get(_ENVIRON_SPAN_KEY)
            enabled = request.environ.get(_ENVIRON_ENABLED_KEY)
            if not span and enabled:
                _logger.warning(
                    "Pyramid environ's OpenTelemetry span missing."
                    "If the OpenTelemetry tween was added manually, make sure"
                    "PyramidInstrumentor().instrument_config(config) is called"
                )
            elif enabled:
                status = getattr(response, "status", status)

                if status is not None:
                    otel_wsgi.add_response_attributes(
                        span,
                        status,
                        getattr(response, "headerlist", None),
                    )

                if span.is_recording() and span.kind == trace.SpanKind.SERVER:
                    custom_attributes = (
                        otel_wsgi.collect_custom_response_headers_attributes(
                            getattr(response, "headerlist", None)))
                    if len(custom_attributes) > 0:
                        span.set_attributes(custom_attributes)

                propagator = get_global_response_propagator()
                if propagator and hasattr(response, "headers"):
                    propagator.inject(response.headers)

                activation = request.environ.get(_ENVIRON_ACTIVATION_KEY)

                # Only considering HTTPServerError
                # to make sure 200, 300 and 400 exceptions are not reported as error
                if isinstance(response, HTTPServerError):
                    activation.__exit__(
                        type(response),
                        response,
                        getattr(response, "__traceback__", None),
                    )
                else:
                    activation.__exit__(None, None, None)

                env_token = request.environ.get(_ENVIRON_TOKEN, None)
                if env_token is not None:
                    context.detach(env_token)

        return response
    def process_response(self, request, response):
        if self._excluded_urls.url_disabled(request.build_absolute_uri("?")):
            return response

        is_asgi_request = _is_asgi_request(request)
        if not _is_asgi_supported and is_asgi_request:
            return response

        activation = request.META.pop(self._environ_activation_key, None)
        span = request.META.pop(self._environ_span_key, None)
        active_requests_count_attrs = request.META.pop(
            self._environ_active_request_attr_key, None
        )
        duration_attrs = request.META.pop(
            self._environ_duration_attr_key, None
        )
        if duration_attrs:
            duration_attrs[
                SpanAttributes.HTTP_STATUS_CODE
            ] = response.status_code
        request_start_time = request.META.pop(self._environ_timer_key, None)

        if activation and span:
            if is_asgi_request:
                set_status_code(span, response.status_code)

                if span.is_recording() and span.kind == SpanKind.SERVER:
                    custom_headers = {}
                    for key, value in response.items():
                        asgi_setter.set(custom_headers, key, value)

                    custom_res_attributes = (
                        asgi_collect_custom_response_attributes(custom_headers)
                    )
                    for key, value in custom_res_attributes.items():
                        span.set_attribute(key, value)
            else:
                add_response_attributes(
                    span,
                    f"{response.status_code} {response.reason_phrase}",
                    response.items(),
                )
                if span.is_recording() and span.kind == SpanKind.SERVER:
                    custom_attributes = (
                        wsgi_collect_custom_response_headers_attributes(
                            response.items()
                        )
                    )
                    if len(custom_attributes) > 0:
                        span.set_attributes(custom_attributes)

            propagator = get_global_response_propagator()
            if propagator:
                propagator.inject(response)

            # record any exceptions raised while processing the request
            exception = request.META.pop(self._environ_exception_key, None)
            if _DjangoMiddleware._otel_response_hook:
                _DjangoMiddleware._otel_response_hook(  # pylint: disable=not-callable
                    span, request, response
                )

            if exception:
                activation.__exit__(
                    type(exception),
                    exception,
                    getattr(exception, "__traceback__", None),
                )
            else:
                activation.__exit__(None, None, None)

        if request_start_time is not None:
            duration = max(
                round((default_timer() - request_start_time) * 1000), 0
            )
            self._duration_histogram.record(duration, duration_attrs)
        self._active_request_counter.add(-1, active_requests_count_attrs)
        if request.META.get(self._environ_token, None) is not None:
            detach(request.META.get(self._environ_token))
            request.META.pop(self._environ_token)

        return response