コード例 #1
0
    async def dispatch(self, request: Request,
                       call_next: RequestResponseEndpoint) -> Response:
        """Processes the whole request APM capturing.

        Args:
            request (Request)
            call_next (RequestResponseEndpoint): Next request process in Starlette.

        Returns:
            Response
        """
        await self._request_started(request)

        try:
            response = await call_next(request)
        except Exception:
            await self.capture_exception(
                context={
                    "request":
                    await get_data_from_request(request, self.client.config,
                                                constants.ERROR)
                })
            zuqa.set_transaction_result("HTTP 5xx", override=False)
            zuqa.set_context({"status_code": 500}, "response")

            raise
        else:
            await self._request_finished(response)
        finally:
            self.client.end_transaction()

        return response
コード例 #2
0
    def call(self, module, method, wrapped, instance, args, kwargs):
        if not hasattr(instance.application, "zuqa_client"):
            # If tornado was instrumented but not as the main framework
            # (i.e. in Flower), we should skip it.
            return wrapped(*args, **kwargs)

        # Late import to avoid ImportErrors
        from tornado.web import Finish, HTTPError
        from zuqa.contrib.tornado.utils import get_data_from_request

        e = args[0]
        if isinstance(e, Finish):
            # Not an error; Finish is an exception that ends a request without an error response
            return wrapped(*args, **kwargs)

        client = instance.application.zuqa_client
        request = instance.request
        client.capture_exception(
            context={
                "request":
                get_data_from_request(instance, request, client.config,
                                      constants.ERROR)
            })
        if isinstance(e, HTTPError):
            zuqa.set_transaction_result("HTTP {}xx".format(
                int(e.status_code / 100)),
                                        override=False)
            zuqa.set_context({"status_code": e.status_code}, "response")
        else:
            zuqa.set_transaction_result("HTTP 5xx", override=False)
            zuqa.set_context({"status_code": 500}, "response")

        return wrapped(*args, **kwargs)
コード例 #3
0
    async def call(self, module, method, wrapped, instance, args, kwargs):
        if not hasattr(instance.application, "zuqa_client"):
            # If tornado was instrumented but not as the main framework
            # (i.e. in Flower), we should skip it.
            return await wrapped(*args, **kwargs)

        # Late import to avoid ImportErrors
        from zuqa.contrib.tornado.utils import get_data_from_request, get_data_from_response

        request = instance.request
        trace_parent = TraceParent.from_headers(request.headers)
        client = instance.application.zuqa_client
        client.begin_transaction("request", trace_parent=trace_parent)
        zuqa.set_context(
            lambda: get_data_from_request(instance, request, client.config,
                                          constants.TRANSACTION), "request")
        # TODO: Can we somehow incorporate the routing rule itself here?
        zuqa.set_transaction_name("{} {}".format(request.method,
                                                 type(instance).__name__),
                                  override=False)

        ret = await wrapped(*args, **kwargs)

        zuqa.set_context(
            lambda: get_data_from_response(instance, client.config, constants.
                                           TRANSACTION), "response")
        result = "HTTP {}xx".format(instance.get_status() // 100)
        zuqa.set_transaction_result(result, override=False)
        client.end_transaction()

        return ret
コード例 #4
0
    def process_response(self, request, response):
        if django_settings.DEBUG and not self.client.config.debug:
            return response
        try:
            if hasattr(response, "status_code"):
                transaction_name = None
                if self.client.config.django_transaction_name_from_route and hasattr(
                        request.resolver_match, "route"):
                    transaction_name = request.resolver_match.route
                elif getattr(request, "_zuqa_view_func", False):
                    transaction_name = get_name_from_func(
                        request._zuqa_view_func)
                if transaction_name:
                    transaction_name = build_name_with_http_method_prefix(
                        transaction_name, request)
                    zuqa.set_transaction_name(transaction_name, override=False)

                zuqa.set_context(
                    lambda: self.client.get_data_from_request(
                        request, constants.TRANSACTION), "request")
                zuqa.set_context(
                    lambda: self.client.get_data_from_response(
                        response, constants.TRANSACTION), "response")
                zuqa.set_context(lambda: self.client.get_user_info(request),
                                 "user")
                zuqa.set_transaction_result("HTTP {}xx".format(
                    response.status_code // 100),
                                            override=False)
        except Exception:
            self.client.error_logger.error(
                "Exception during timing of request", exc_info=True)
        return response
コード例 #5
0
    async def handle_request(request, handler):
        zuqa_client = app.get(CLIENT_KEY)
        if zuqa_client:
            request[CLIENT_KEY] = zuqa_client
            trace_parent = AioHttpTraceParent.from_headers(request.headers)
            zuqa_client.begin_transaction("request", trace_parent=trace_parent)
            resource = request.match_info.route.resource
            name = request.method
            if resource:
                # canonical has been added in 3.3, and returns one of path, formatter, prefix
                for attr in ("canonical", "_path", "_formatter", "_prefix"):
                    if hasattr(resource, attr):
                        name += " " + getattr(resource, attr)
                        break
                else:
                    name += " unknown route"
            else:
                name += " unknown route"
            zuqa.set_transaction_name(name, override=False)
            zuqa.set_context(
                lambda: get_data_from_request(request, zuqa_client.config,
                                              constants.TRANSACTION),
                "request")

        try:
            response = await handler(request)
            zuqa.set_transaction_result("HTTP {}xx".format(response.status //
                                                           100),
                                        override=False)
            zuqa.set_context(
                lambda: get_data_from_response(response, zuqa_client.config,
                                               constants.TRANSACTION),
                "response")
            return response
        except Exception as exc:
            if zuqa_client:
                zuqa_client.capture_exception(
                    context={
                        "request":
                        get_data_from_request(request, zuqa_client.config,
                                              constants.ERROR)
                    })
                zuqa.set_transaction_result("HTTP 5xx", override=False)
                zuqa.set_context({"status_code": 500}, "response")
                # some exceptions are response-like, e.g. have headers and status code. Let's try and capture them
                if isinstance(exc, (Response, HTTPException)):
                    zuqa.set_context(
                        lambda:
                        get_data_from_response(exc, zuqa_client.config,
                                               constants.ERROR),  # noqa: F821
                        "response",
                    )

            raise
        finally:
            zuqa_client.end_transaction()
コード例 #6
0
    async def _request_finished(self, response: Response):
        """Captures the end of the request processing to APM.

        Args:
            response (Response)
        """
        await set_context(
            lambda: get_data_from_response(response, self.client.config,
                                           constants.TRANSACTION), "response")

        result = "HTTP {}xx".format(response.status_code // 100)
        zuqa.set_transaction_result(result, override=False)
コード例 #7
0
 def request_finished(self, app, response):
     if not self.app.debug or self.client.config.debug:
         zuqa.set_context(
             lambda: get_data_from_response(response, self.client.config,
                                            constants.TRANSACTION),
             "response")
         if response.status_code:
             result = "HTTP {}xx".format(response.status_code // 100)
         else:
             result = response.status
         zuqa.set_transaction_result(result, override=False)
         # Instead of calling end_transaction here, we defer the call until the response is closed.
         # This ensures that we capture things that happen until the WSGI server closes the response.
         response.call_on_close(self.client.end_transaction)
コード例 #8
0
 def transaction_name():
     zuqa.set_transaction_name("foo")
     zuqa.set_transaction_result("okydoky")
     return Response("")
コード例 #9
0
def override_transaction_name_view(request):
    zuqa.set_transaction_name("foo")
    zuqa.set_transaction_result("okydoky")
    return HttpResponse()