コード例 #1
0
    def process_request(self, req, resp):
        if self._do_nothing:
            return
        if self.api is None and self.hug_http_interface is not None:
            self.api = self.hug_http_interface.falcon
        tracked_request = TrackedRequest.instance()
        tracked_request.is_real_request = True
        req.context.scout_tracked_request = tracked_request
        tracked_request.start_span(operation="Middleware",
                                   should_capture_backtrace=False)

        path = req.path
        # Falcon URL parameter values are *either* single items or lists
        url_params = [(k, v) for k, vs in req.params.items()
                      for v in (vs if isinstance(vs, list) else [vs])]
        tracked_request.tag("path", create_filtered_path(path, url_params))
        if ignore_path(path):
            tracked_request.tag("ignore_transaction", True)

        if scout_config.value("collect_remote_ip"):
            # Determine a remote IP to associate with the request. The value is
            # spoofable by the requester so this is not suitable to use in any
            # security sensitive context.
            user_ip = (req.get_header("x-forwarded-for",
                                      default="").split(",")[0]
                       or req.get_header("client-ip", default="").split(",")[0]
                       or req.remote_addr)
            tracked_request.tag("user_ip", user_ip)

        queue_time = req.get_header(
            "x-queue-start", default="") or req.get_header("x-request-start",
                                                           default="")
        track_request_queue_time(queue_time, tracked_request)
コード例 #2
0
    def after_request(self):
        if self._do_nothing:
            return
        request = cherrypy.request
        tracked_request = getattr(request, "_scout_tracked_request", None)
        if tracked_request is None:
            return

        # Rename controller span now routing has been done
        operation_name = get_operation_name(request)
        if operation_name is not None:
            request._scout_controller_span.operation = operation_name

        # Grab general request data now it has been parsed
        path = request.path_info
        # Parse params ourselves because we want only GET params but CherryPy
        # parses POST params (nearly always sensitive) into the same dict.
        params = parse_qsl(request.query_string)
        tracked_request.tag("path", create_filtered_path(path, params))
        if ignore_path(path):
            tracked_request.tag("ignore_transaction", True)

        if scout_config.value("collect_remote_ip"):
            # Determine a remote IP to associate with the request. The value is
            # spoofable by the requester so this is not suitable to use in any
            # security sensitive context.
            user_ip = (request.headers.get("x-forwarded-for", "").split(",")[0]
                       or request.headers.get("client-ip", "").split(",")[0]
                       or (request.remote.ip or None))
            tracked_request.tag("user_ip", user_ip)

        queue_time = request.headers.get(
            "x-queue-start", "") or request.headers.get("x-request-start", "")
        track_request_queue_time(queue_time, tracked_request)

        response = cherrypy.response
        status = response.status
        if isinstance(status, int):
            status_int = status
        else:
            status_first = status.split(" ", 1)[0]
            try:
                status_int = int(status_first)
            except ValueError:
                # Assume OK
                status_int = 200
        if 500 <= status_int <= 599:
            tracked_request.tag("error", "true")
        elif status_int == 404:
            tracked_request.is_real_request = False

        tracked_request.stop_span()
コード例 #3
0
    def process_request(self, request):
        if not scout_config.value("monitor"):
            return
        tracked_request = TrackedRequest.instance()
        request._scout_tracked_request = tracked_request

        queue_time = request.META.get(
            "HTTP_X_QUEUE_START") or request.META.get("HTTP_X_REQUEST_START",
                                                      "")
        track_request_queue_time(queue_time, tracked_request)

        tracked_request.start_span(operation="Middleware",
                                   should_capture_backtrace=False)
コード例 #4
0
    def process_request(self, req, resp):
        tracked_request = TrackedRequest.instance()
        tracked_request.is_real_request = True
        req.context.scout_tracked_request = tracked_request

        path = req.path
        # Falcon URL parameter values are *either* single items or lists
        url_params = [
            (k, v)
            for k, vs in req.params.items()
            for v in (vs if isinstance(vs, list) else [vs])
        ]
        tracked_request.tag("path", create_filtered_path(path, url_params))
        if ignore_path(path):
            tracked_request.tag("ignore_transaction", True)

        # Determine a remote IP to associate with the request. The value is
        # spoofable by the requester so this is not suitable to use in any
        # security sensitive context.
        user_ip = (
            req.get_header("x-forwarded-for", default="").split(",")[0]
            or req.get_header("client-ip", default="").split(",")[0]
            or req.remote_addr
        )
        tracked_request.tag("user_ip", user_ip)

        queue_time = req.get_header("x-queue-start", default="") or req.get_header(
            "x-request-start", default=""
        )
        tracked_queue_time = track_request_queue_time(queue_time, tracked_request)
        if not tracked_queue_time:
            amazon_queue_time = req.get_header("x-amzn-trace-id", default="")
            track_amazon_request_queue_time(amazon_queue_time, tracked_request)
コード例 #5
0
    def __call__(self, request):
        if not scout_config.value("monitor"):
            return self.get_response(request)

        tracked_request = TrackedRequest.instance()

        queue_time = request.META.get(
            "HTTP_X_QUEUE_START") or request.META.get("HTTP_X_REQUEST_START",
                                                      "")
        track_request_queue_time(queue_time, tracked_request)

        with tracked_request.span(
                operation="Middleware",
                should_capture_backtrace=False,
        ):
            return self.get_response(request)
コード例 #6
0
ファイル: pyramid.py プロジェクト: scoutapp/scout_apm_python
    def scout_tween(request):
        tracked_request = TrackedRequest.instance()

        with tracked_request.span(operation="Controller/Pyramid",
                                  should_capture_backtrace=False) as span:
            path = request.path
            # mixed() returns values as *either* single items or lists
            url_params = [(k, v)
                          for k, vs in request.GET.dict_of_lists().items()
                          for v in vs]
            tracked_request.tag("path", create_filtered_path(path, url_params))
            if ignore_path(path):
                tracked_request.tag("ignore_transaction", True)

            if scout_config.value("collect_remote_ip"):
                # Determine a remote IP to associate with the request. The value is
                # spoofable by the requester so this is not suitable to use in any
                # security sensitive context.
                user_ip = (request.headers.get("x-forwarded-for",
                                               default="").split(",")[0]
                           or request.headers.get("client-ip",
                                                  default="").split(",")[0]
                           or request.remote_addr)
                tracked_request.tag("user_ip", user_ip)

            queue_time = request.headers.get(
                "x-queue-start", default="") or request.headers.get(
                    "x-request-start", default="")
            track_request_queue_time(queue_time, tracked_request)

            try:
                try:
                    response = handler(request)
                finally:
                    # Routing lives further down the call chain. So time it
                    # starting above, but only set the name if it gets a name
                    if request.matched_route is not None:
                        tracked_request.is_real_request = True
                        span.operation = "Controller/" + request.matched_route.name
            except Exception:
                tracked_request.tag("error", "true")
                raise

            if 500 <= response.status_code <= 599:
                tracked_request.tag("error", "true")

        return response
コード例 #7
0
def wrap_callback(wrapped, instance, args, kwargs):
    tracked_request = TrackedRequest.instance()
    tracked_request.is_real_request = True

    path = request.path
    # allitems() is an undocumented bottle internal
    tracked_request.tag("path",
                        create_filtered_path(path, request.query.allitems()))
    if ignore_path(path):
        tracked_request.tag("ignore_transaction", True)

    if request.route.name is not None:
        controller_name = request.route.name
    else:
        controller_name = request.route.rule
    if controller_name == "/":
        controller_name = "/home"
    if not controller_name.startswith("/"):
        controller_name = "/" + controller_name

    if scout_config.value("collect_remote_ip"):
        # Determine a remote IP to associate with the request. The
        # value is spoofable by the requester so this is not suitable
        # to use in any security sensitive context.
        user_ip = (request.headers.get("x-forwarded-for", "").split(",")[0]
                   or request.headers.get("client-ip", "").split(",")[0]
                   or request.environ.get("REMOTE_ADDR"))
        tracked_request.tag("user_ip", user_ip)

    queue_time = request.headers.get(
        "x-queue-start", "") or request.headers.get("x-request-start", "")
    track_request_queue_time(queue_time, tracked_request)

    with tracked_request.span(operation="Controller{}".format(controller_name),
                              should_capture_backtrace=False):
        try:
            value = wrapped(*args, **kwargs)
        except Exception:
            tracked_request.tag("error", "true")
            raise
        else:
            if 500 <= response.status_code <= 599:
                tracked_request.tag("error", "true")
            return value
コード例 #8
0
def test_track_request_queue_time_valid(with_t, tracked_request):
    queue_start = int(datetime_to_timestamp(dt.datetime.utcnow())) - 2
    if with_t:
        header_value = str("t=") + str(queue_start)
    else:
        header_value = str(queue_start)

    result = track_request_queue_time(header_value, tracked_request)

    assert result is True
    queue_time_ns = tracked_request.tags["scout.queue_time_ns"]
    assert isinstance(queue_time_ns, int) and queue_time_ns > 0
コード例 #9
0
def test_track_request_queue_time_valid(with_t, tracked_request):
    queue_start = int(datetime_to_timestamp(dt.datetime.utcnow())) - 2
    if with_t:
        header_value = str("t=") + str(queue_start)
    else:
        header_value = str(queue_start)

    result = track_request_queue_time(header_value, tracked_request)

    assert result is True
    queue_time_ns = tracked_request.tags["scout.queue_time_ns"]
    # Upper bound assumes we didn't take more than 2s to run this test...
    assert queue_time_ns >= 2000000000 and queue_time_ns < 4000000000
コード例 #10
0
    def __call__(self, request):
        if not scout_config.value("monitor"):
            return self.get_response(request)

        tracked_request = TrackedRequest.instance()

        tracked_request.start_span(operation="Middleware",
                                   should_capture_backtrace=False)
        queue_time = request.META.get(
            "HTTP_X_QUEUE_START") or request.META.get("HTTP_X_REQUEST_START",
                                                      "")
        queue_time_tracked = track_request_queue_time(queue_time,
                                                      tracked_request)
        if not queue_time_tracked:
            track_amazon_request_queue_time(
                request.META.get("HTTP_X_AMZN_TRACE_ID", ""), tracked_request)

        try:
            return self.get_response(request)
        finally:
            tracked_request.stop_span()
コード例 #11
0
def test_track_request_queue_time_invalid(header_value, tracked_request):
    result = track_request_queue_time(header_value, tracked_request)

    assert result is False
    assert "scout.queue_time_ns" not in tracked_request.tags
コード例 #12
0
    async def __call__(self, scope, receive, send):
        if self._do_nothing or scope["type"] != "http":
            await self.app(scope, receive, send)
            return

        request = Request(scope)
        tracked_request = TrackedRequest.instance()
        # Can't name controller until post-routing - see final clause
        controller_span = tracked_request.start_span(operation="Controller/Unknown")

        tracked_request.tag(
            "path",
            create_filtered_path(request.url.path, request.query_params.multi_items()),
        )
        if ignore_path(request.url.path):
            tracked_request.tag("ignore_transaction", True)

        user_ip = (
            request.headers.get("x-forwarded-for", default="").split(",")[0]
            or request.headers.get("client-ip", default="").split(",")[0]
            or request.client.host
        )
        tracked_request.tag("user_ip", user_ip)

        queue_time = request.headers.get(
            "x-queue-start", default=""
        ) or request.headers.get("x-request-start", default="")
        tracked_queue_time = track_request_queue_time(queue_time, tracked_request)
        if not tracked_queue_time:
            amazon_queue_time = request.headers.get("x-amzn-trace-id", default="")
            track_amazon_request_queue_time(amazon_queue_time, tracked_request)

        def grab_extra_data():
            if "endpoint" in scope:
                # Rename top span
                endpoint = scope["endpoint"]
                controller_span.operation = "Controller/{}.{}".format(
                    endpoint.__module__, endpoint.__qualname__
                )
                tracked_request.is_real_request = True

            # From AuthenticationMiddleware - bypass request.user because it
            # throws AssertionError if 'user' is not in Scope, and we need a
            # try/except already
            try:
                username = scope["user"].display_name
            except (KeyError, AttributeError):
                pass
            else:
                tracked_request.tag("username", username)

        async def wrapped_send(data):
            # Finish HTTP span when body finishes sending, not later (e.g.
            # after background tasks)
            if data.get("type", None) == "http.response.body" and not data.get(
                "more_body", False
            ):
                grab_extra_data()
                tracked_request.stop_span()
            return await send(data)

        try:
            await self.app(scope, receive, wrapped_send)
        except Exception as exc:
            tracked_request.tag("error", "true")
            raise exc
        finally:
            if tracked_request.end_time is None:
                grab_extra_data()
                tracked_request.stop_span()