Ejemplo n.º 1
0
def __create_segment(request, recorder, lambda_ctx=False):
    headers = request.headers
    xray_header = construct_xray_header(headers)

    name = calculate_segment_name(request.host, recorder)

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

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

    return segment
Ejemplo n.º 2
0
    def on_request(self, host: http.Host, headers: http.Headers,
                   method: http.Method, path: http.Path, url: http.URL):
        xray_header = construct_xray_header(headers)

        name = calculate_segment_name(host, self._recorder)

        sampling_decision = calculate_sampling_decision(
            trace_header=xray_header,
            recorder=self._recorder,
            service_name=host,
            method=method,
            path=path)

        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(xray_http.URL, url)
        segment.put_http_meta(xray_http.METHOD, method)
        segment.put_http_meta(xray_http.USER_AGENT, headers.get('User-Agent'))

        client_ip = headers.get('X-Forwarded-For') or headers.get(
            'HTTP_X_FORWARDED_FOR')
        if client_ip:
            segment.put_http_meta(xray_http.CLIENT_IP, client_ip)
            segment.put_http_meta(xray_http.X_FORWARDED_FOR, True)
Ejemplo n.º 3
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
Ejemplo n.º 4
0
    def process_request(self, req, resp):
        try:
            logging.info('initializing xray middleware')
            self._recorder = xray_recorder
            self._recorder.configure(plugins=('EC2Plugin', 'ECSPlugin'),
                                     daemon_address='localhost:2000')

            headers = req.headers
            xray_header = construct_xray_header(headers)

            name = calculate_segment_name(req.host, self._recorder)

            sampling_decision = calculate_sampling_decision(
                trace_header=xray_header,
                recorder=self._recorder,
                service_name=req.host,
                method=req.method,
                path=req.path,
            )

            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, req.uri)
            segment.put_http_meta(http.METHOD, req.method)
            segment.put_http_meta(http.USER_AGENT, headers.get('User-Agent'))
            segment.put_metadata('x-ray_middleware', {
                'uri': req.uri,
                'method': req.method,
                'request': req.media
            }, __name__)
            segment.put_annotation('dateTime',
                                   strftime("%Y-%m-%d %H:%M:%S", gmtime()))

            client_ip = headers.get('X-Forwarded-For') or headers.get(
                'HTTP_X_FORWARDED_FOR')
            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, req.remote_addr)

        except Exception as e:
            log.debug(str(e))
            self._handler_exception(e)
Ejemplo n.º 5
0
    def _before_request(self):
        headers = request.headers
        xray_header = construct_xray_header(headers)
        req = request._get_current_object()

        name = calculate_segment_name(req.host, self._recorder)

        sampling_req = {
            'host': req.host,
            'method': req.method,
            'path': req.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, req.base_url)
        segment.put_http_meta(http.METHOD, req.method)
        segment.put_http_meta(http.USER_AGENT, headers.get('User-Agent'))

        client_ip = headers.get('X-Forwarded-For') or headers.get(
            'HTTP_X_FORWARDED_FOR')
        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, req.remote_addr)
Ejemplo n.º 6
0
    def _xray_hook_before(self, *args, **kwargs):
        request = self.request

        xray_header = construct_xray_header(request.headers)

        host = request.headers.get('Host')
        name = calculate_segment_name(host, xray_recorder)

        sampling_decision = calculate_sampling_decision(
            trace_header=xray_header,
            recorder=xray_recorder,
            service_name=host,
            method=request.method,
            path=request.path,
        )

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

        segment.put_http_meta(http.URL, request.path)
        segment.put_annotation('query', request.query)
        segment.put_http_meta(http.METHOD, request.method)

        user_agent = request.headers.get('User-Agent')
        if user_agent:
            segment.put_http_meta(http.USER_AGENT, user_agent)

        x_forwarded_for = request.headers.get('X-Forwarded-For')
        remote_ip = request.headers.get('remote_ip')

        if x_forwarded_for:
            # 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, x_forwarded_for)
            segment.put_http_meta(http.X_FORWARDED_FOR, True)
        elif remote_ip:
            segment.put_http_meta(http.CLIENT_IP, remote_ip)
Ejemplo n.º 7
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
Ejemplo n.º 8
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
Ejemplo n.º 9
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
Ejemplo n.º 10
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_decision = calculate_sampling_decision(
        trace_header=xray_header,
        recorder=xray_recorder,
        service_name=request.headers['host'],
        method=request.method,
        path=request.path,
    )

    # Start a segment
    segment = xray_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.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 Exception as err:
        # Store exception information including the stacktrace to the segment
        segment = xray_recorder.current_segment()
        segment.put_http_meta(http.STATUS, 500)
        stack = traceback.extract_stack(limit=xray_recorder._max_trace_back)
        segment.add_exception(err, stack)
        xray_recorder.end_segment()
        raise

    # Store response metadata into the current segment
    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)

    # Close segment so it can be dispatched off to the daemon
    xray_recorder.end_segment()
    return response
Ejemplo n.º 11
0
async def before_request(request: Request) -> None:
    """
    The request middleware that runs when Sanic receives a
    request. Starts a segment if sampling determines if
    it should be traced.
    """
    xray_recorder = request.app.xray_recorder

    headers = request.headers
    xray_header = construct_xray_header(headers)

    name = calculate_segment_name(request.host, xray_recorder)

    # custom decision to skip if INCENDIARY_XRAY_ENABLED is false
    sampling_decision = xray_recorder.sampler.calculate_sampling_decision(
        trace_header=xray_header,
        recorder=xray_recorder,
        service_name=request.host,
        method=request.method,
        path=request.path,
    )

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

    if segment.sampled:
        segment.save_origin_trace_header(xray_header)
        segment.put_annotation("insanic_version", __version__)
        segment.put_annotation("service_version",
                               settings.get("APPLICATION_VERSION", "?"))
        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 = headers.get(settings.FORWARDED_FOR_HEADER) or headers.get(
            "HTTP_X_FORWARDED_FOR")
        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)

        attributes = [
            "args",
            "content_type",
            "cookies",
            "data",
            "host",
            "ip",
            "method",
            "path",
            "scheme",
            "url",
        ]
        for attr in attributes:
            if hasattr(request, attr):
                payload = getattr(request, attr)

                if isinstance(payload, dict):
                    payload = abbreviate_for_xray(get_safe_dict(payload))
                payload = json.dumps(payload)

                segment.put_metadata(f"{attr}", payload, "request")