Esempio n. 1
0
def _after_request(request, response):
    global in_lambda_ctx
    global _recorder
    in_lambda_ctx = False

    if check_in_lambda() and type(_recorder.context) == LambdaContext:
        in_lambda_ctx = True

    if in_lambda_ctx:
        segment = _recorder.current_subsegment()
    else:
        try:
            segment = _recorder.current_segment()
        except SegmentNotFoundException:
            segment = __create_segment(request,
                                       _recorder,
                                       lambda_ctx=in_lambda_ctx)
    segment.put_http_meta(http.STATUS, response.status_code)

    origin_header = segment.get_origin_trace_header()
    resp_header_str = prepare_response_header(origin_header, segment)
    response.headers[http.XRAY_HEADER] = resp_header_str

    cont_len = response.headers.get('Content-Length')
    if cont_len:
        segment.put_http_meta(http.CONTENT_LENGTH, int(cont_len))

    if in_lambda_ctx:
        _recorder.end_subsegment()
    else:
        _recorder.end_segment()
    return response
Esempio n. 2
0
    def __call__(self, request):

        sampling_decision = None
        meta = request.META
        xray_header = construct_xray_header(meta)
        # a segment name is required
        name = calculate_segment_name(meta.get(HOST_KEY), xray_recorder)

        sampling_req = {
            'host': meta.get(HOST_KEY),
            'method': request.method,
            'path': request.path,
            'service': name,
        }
        sampling_decision = calculate_sampling_decision(
            trace_header=xray_header,
            recorder=xray_recorder,
            sampling_req=sampling_req,
        )

        if self.in_lambda_ctx:
            segment = xray_recorder.begin_subsegment(name)
        else:
            segment = xray_recorder.begin_segment(
                name=name,
                traceid=xray_header.root,
                parent_id=xray_header.parent,
                sampling=sampling_decision,
            )

        segment.save_origin_trace_header(xray_header)
        segment.put_http_meta(http.URL, request.build_absolute_uri())
        segment.put_http_meta(http.METHOD, request.method)

        if meta.get(USER_AGENT_KEY):
            segment.put_http_meta(http.USER_AGENT, meta.get(USER_AGENT_KEY))
        if meta.get(X_FORWARDED_KEY):
            # X_FORWARDED_FOR may come from untrusted source so we
            # need to set the flag to true as additional information
            segment.put_http_meta(http.CLIENT_IP, meta.get(X_FORWARDED_KEY))
            segment.put_http_meta(http.X_FORWARDED_FOR, True)
        elif meta.get(REMOTE_ADDR_KEY):
            segment.put_http_meta(http.CLIENT_IP, meta.get(REMOTE_ADDR_KEY))

        response = self.get_response(request)
        segment.put_http_meta(http.STATUS, response.status_code)

        if response.has_header(CONTENT_LENGTH_KEY):
            length = int(response[CONTENT_LENGTH_KEY])
            segment.put_http_meta(http.CONTENT_LENGTH, length)
        response[http.XRAY_HEADER] = prepare_response_header(
            xray_header, segment)

        if self.in_lambda_ctx:
            xray_recorder.end_subsegment()
        else:
            xray_recorder.end_segment()

        return response
Esempio n. 3
0
    def on_response(self, response: http.Response, exc: Exception = None):
        segment = self._recorder.current_segment()
        segment.put_http_meta(xray_http.STATUS, response.status_code)

        origin_header = segment.get_origin_trace_header()
        resp_header_str = prepare_response_header(origin_header, segment)
        response.headers[xray_http.XRAY_HEADER] = resp_header_str

        cont_len = response.headers.get('Content-Length')
        if cont_len:
            segment.put_http_meta(xray_http.CONTENT_LENGTH, int(cont_len))
        self._recorder.end_segment()
Esempio n. 4
0
    def _after_request(self, response):
        segment = self._recorder.current_segment()
        segment.put_http_meta(http.STATUS, response.status_code)

        origin_header = segment.get_origin_trace_header()
        resp_header_str = prepare_response_header(origin_header, segment)
        response.headers[http.XRAY_HEADER] = resp_header_str

        cont_len = response.headers.get('Content-Length')
        if cont_len:
            segment.put_http_meta(http.CONTENT_LENGTH, int(cont_len))

        self._recorder.end_segment()
        return response
Esempio n. 5
0
async def middleware(request, handler):
    """
    Main middleware function, deals with all the X-Ray segment logic
    """
    # Create X-Ray headers
    xray_header = construct_xray_header(request.headers)
    # Get name of service or generate a dynamic one from host
    name = calculate_segment_name(request.headers['host'].split(':', 1)[0],
                                  xray_recorder)

    sampling_req = {
        'host': request.headers['host'],
        'method': request.method,
        'path': request.path,
        'service': name,
    }

    sampling_decision = calculate_sampling_decision(
        trace_header=xray_header,
        recorder=xray_recorder,
        sampling_req=sampling_req,
    )

    # Start a segment
    segment = xray_recorder.begin_segment(
        name=name,
        traceid=xray_header.root,
        parent_id=xray_header.parent,
        sampling=sampling_decision,
    )

    segment.save_origin_trace_header(xray_header)
    # Store request metadata in the current segment
    segment.put_http_meta(http.URL, str(request.url))
    segment.put_http_meta(http.METHOD, request.method)

    if 'User-Agent' in request.headers:
        segment.put_http_meta(http.USER_AGENT, request.headers['User-Agent'])

    if 'X-Forwarded-For' in request.headers:
        segment.put_http_meta(http.CLIENT_IP,
                              request.headers['X-Forwarded-For'])
        segment.put_http_meta(http.X_FORWARDED_FOR, True)
    elif 'remote_addr' in request.headers:
        segment.put_http_meta(http.CLIENT_IP, request.headers['remote_addr'])
    else:
        segment.put_http_meta(http.CLIENT_IP, request.remote)

    try:
        # Call next middleware or request handler
        response = await handler(request)
    except HTTPException as exc:
        # Non 2XX responses are raised as HTTPExceptions
        response = exc
        raise
    except Exception as err:
        # Store exception information including the stacktrace to the segment
        response = None
        segment.put_http_meta(http.STATUS, 500)
        stack = stacktrace.get_stacktrace(limit=xray_recorder.max_trace_back)
        segment.add_exception(err, stack)
        raise
    finally:
        if response is not None:
            segment.put_http_meta(http.STATUS, response.status)
            if 'Content-Length' in response.headers:
                length = int(response.headers['Content-Length'])
                segment.put_http_meta(http.CONTENT_LENGTH, length)

            header_str = prepare_response_header(xray_header, segment)
            response.headers[http.XRAY_HEADER] = header_str

        xray_recorder.end_segment()

    return response
Esempio n. 6
0
    async def dispatch(self, request: Request,
                       call_next: RequestResponseEndpoint) -> Response:
        """
        Main middleware function, deals with all the X-Ray segment logic
        """

        # Create X-Ray headers
        headers = request.headers

        xray_header = construct_xray_header(headers)
        # Get name of service or generate a dynamic one from host
        name = calculate_segment_name(headers["host"].split(":", 1)[0],
                                      self._recorder)

        sampling_req = {
            "host": headers["host"],
            "method": request.method,
            "path": request.url.path,
            "service": name,
        }

        sampling_decision = calculate_sampling_decision(
            trace_header=xray_header,
            recorder=self._recorder,
            sampling_req=sampling_req)

        # Start a segment
        if self.in_lambda_ctx:
            segment = self._recorder.begin_subsegment(name)
        else:
            segment = self._recorder.begin_segment(
                name=name,
                traceid=xray_header.root,
                parent_id=xray_header.parent,
                sampling=sampling_decision,
            )

        # Store request metadata in the current segment
        segment.save_origin_trace_header(xray_header)
        segment.put_http_meta(http.URL, str(request.url))
        segment.put_http_meta(http.METHOD, request.method)

        if "User-Agent" in request.headers:
            segment.put_http_meta(http.USER_AGENT,
                                  request.headers["User-Agent"])

        if "X-Forwarded-For" in request.headers:
            segment.put_http_meta(http.CLIENT_IP,
                                  request.headers["X-Forwarded-For"])
            segment.put_http_meta(http.X_FORWARDED_FOR, True)
        elif "remote_addr" in request.headers:
            segment.put_http_meta(http.CLIENT_IP,
                                  request.headers["remote_addr"])
        else:
            segment.put_http_meta(http.CLIENT_IP,
                                  f"{request.client[0]}:{request.client[1]}")

        try:
            # Call next middleware or request handler
            response = await call_next(request)

            segment.put_http_meta(http.STATUS, response.status_code)
            if "Content-Length" in response.headers:
                length = int(response.headers["Content-Length"])
                segment.put_http_meta(http.CONTENT_LENGTH, length)

            header_str = prepare_response_header(xray_header, segment)
            response.headers[http.XRAY_HEADER] = header_str
        except HTTPException as exc:
            segment.put_http_meta(http.STATUS, exc.status_code)
            raise
        except Exception as err:
            # Store exception information including the stacktrace to the segment
            segment.put_http_meta(http.STATUS, 500)
            stack = stacktrace.get_stacktrace(
                limit=xray_recorder.max_trace_back)
            segment.add_exception(err, stack)
            raise
        finally:

            if self.in_lambda_ctx:
                self._recorder.end_subsegment()
            else:
                self._recorder.end_segment()

        return response
Esempio n. 7
0
        def wrapper(*a, **ka):
            headers = request.headers
            xray_header = construct_xray_header(headers)
            name = calculate_segment_name(request.urlparts[1], self._recorder)

            sampling_req = {
                'host': request.urlparts[1],
                'method': request.method,
                'path': request.path,
                'service': name,
            }
            sampling_decision = calculate_sampling_decision(
                trace_header=xray_header,
                recorder=self._recorder,
                sampling_req=sampling_req,
            )

            if self._in_lambda_ctx:
                segment = self._recorder.begin_subsegment(name)
            else:
                segment = self._recorder.begin_segment(
                    name=name,
                    traceid=xray_header.root,
                    parent_id=xray_header.parent,
                    sampling=sampling_decision,
                )

            segment.save_origin_trace_header(xray_header)
            segment.put_http_meta(http.URL, request.url)
            segment.put_http_meta(http.METHOD, request.method)
            segment.put_http_meta(http.USER_AGENT, headers.get('User-Agent'))

            client_ip = request.environ.get(
                'HTTP_X_FORWARDED_FOR') or request.environ.get('REMOTE_ADDR')
            if client_ip:
                segment.put_http_meta(http.CLIENT_IP, client_ip)
                segment.put_http_meta(http.X_FORWARDED_FOR, True)
            else:
                segment.put_http_meta(http.CLIENT_IP, request.remote_addr)

            try:
                rv = callback(*a, **ka)
            except Exception as resp:
                segment.put_http_meta(http.STATUS,
                                      getattr(resp, 'status_code', 500))
                stack = stacktrace.get_stacktrace(
                    limit=self._recorder._max_trace_back)
                segment.add_exception(resp, stack)
                if self._in_lambda_ctx:
                    self._recorder.end_subsegment()
                else:
                    self._recorder.end_segment()

                raise resp

            segment.put_http_meta(http.STATUS, response.status_code)

            origin_header = segment.get_origin_trace_header()
            resp_header_str = prepare_response_header(origin_header, segment)
            response.set_header(http.XRAY_HEADER, resp_header_str)

            cont_len = response.headers.get('Content-Length')
            if cont_len:
                segment.put_http_meta(http.CONTENT_LENGTH, int(cont_len))

            if self._in_lambda_ctx:
                self._recorder.end_subsegment()
            else:
                self._recorder.end_segment()

            return rv