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
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)
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
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)
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)
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)
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
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
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
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
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")