async def handle_request(request, handler): elasticapm_client = app.get(CLIENT_KEY) if elasticapm_client: request[CLIENT_KEY] = elasticapm_client trace_parent = AioHttpTraceParent.from_headers(request.headers) elasticapm_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" elasticapm.set_transaction_name(name, override=False) elasticapm.set_context( lambda: get_data_from_request(request, elasticapm_client. config, constants.TRANSACTION), "request") try: response = await handler(request) elasticapm.set_transaction_result("HTTP {}xx".format( response.status // 100), override=False) elasticapm.set_context( lambda: get_data_from_response(response, elasticapm_client. config, constants.TRANSACTION), "response") return response except Exception as exc: if elasticapm_client: elasticapm_client.capture_exception( context={ "request": get_data_from_request( request, elasticapm_client.config, constants.ERROR) }) elasticapm.set_transaction_result("HTTP 5xx", override=False) elasticapm.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)): elasticapm.set_context( lambda: get_data_from_response( exc, elasticapm_client.config, constants.ERROR ), # noqa: F821 "response", ) raise finally: elasticapm_client.end_transaction()
async def handle_request(request, handler): elasticapm_client = app.get(CLIENT_KEY) if elasticapm_client: request[CLIENT_KEY] = elasticapm_client trace_parent = AioHttpTraceParent.from_headers(request.headers) elasticapm_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" elasticapm.set_transaction_name(name, override=False) elasticapm.set_context( lambda: get_data_from_request( request, capture_body=elasticapm_client.config.capture_body in ("transactions", "all"), capture_headers=elasticapm_client.config.capture_headers, ), "request", ) try: response = await handler(request) elasticapm.set_transaction_result("HTTP {}xx".format( response.status // 100), override=False) elasticapm.set_context( lambda: get_data_from_response( response, capture_headers=elasticapm_client.config.capture_headers), "response", ) return response except Exception: if elasticapm_client: elasticapm_client.capture_exception( context={ "request": get_data_from_request(request, capture_body=elasticapm_client. config.capture_body in ( "all", "errors")) }) elasticapm.set_transaction_result("HTTP 5xx", override=False) elasticapm.set_context({"status_code": 500}, "response") raise finally: elasticapm_client.end_transaction()
async def handle_request(request, handler): elasticapm_client = get_client() if client is None else client should_trace = elasticapm_client and not elasticapm_client.should_ignore_url( request.path) if should_trace: trace_parent = AioHttpTraceParent.from_headers(request.headers) elasticapm_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" elasticapm.set_transaction_name(name, override=False) elasticapm.set_context( lambda: get_data_from_request(request, elasticapm_client. config, constants.TRANSACTION), "request") try: response = await handler(request) if should_trace: elasticapm.set_transaction_result("HTTP {}xx".format( response.status // 100), override=False) elasticapm.set_transaction_outcome( http_status_code=response.status, override=False) elasticapm.set_context( lambda: get_data_from_response(response, elasticapm_client.config, constants.TRANSACTION), "response", ) return response except HTTPException as exc: # HTTPExceptions are response-like, e.g. have headers and status code. They can represent an HTTP # response below a 500 status code and therefore not something to capture as exception. Like # HTTPOk can be raised but will most likely be wrongly tagged as an APM error. Let's try and # capture this according to the status. if exc.status_code < 500 and not should_trace: raise if elasticapm_client: elasticapm.set_transaction_result("HTTP {}xx".format( exc.status_code // 100), override=False) elasticapm.set_transaction_outcome( http_status_code=exc.status_code, override=False) elasticapm.set_context( lambda: get_data_from_response( exc, # noqa: F821 elasticapm_client.config, constants.ERROR if exc.status_code >= 500 else constants.TRANSACTION, # noqa: F821 ), "response", ) if exc.status_code >= 500: elasticapm_client.capture_exception( context={ "request": get_data_from_request(request, elasticapm_client. config, constants.ERROR) }) raise except Exception: if elasticapm_client: elasticapm.set_transaction_result("HTTP 5xx", override=False) elasticapm.set_transaction_outcome(http_status_code=500, override=False) elasticapm.set_context({"status_code": 500}, "response") elasticapm_client.capture_exception( context={ "request": get_data_from_request( request, elasticapm_client.config, constants.ERROR) }) raise finally: elasticapm_client.end_transaction()