def create_app(default_cors_options: CORSOptions) -> Tuple[web.Application, Iterable[WebMiddleware]]: app = web.Application() app['api_versions'] = (1, 2, 3, 4) app.on_startup.append(init) app.on_shutdown.append(shutdown) # middleware must be wrapped by web.middleware at the outermost level. return app, [web.middleware(apartial(rlim_middleware, app))]
def create_app(default_cors_options): app = web.Application() app['api_versions'] = (1, 2, 3, 4) app.on_startup.append(init) app.on_shutdown.append(shutdown) # middleware must be wrapped by web.middleware at the outermost level. return app, [web.middleware(functools.partial(rlim_middleware, app))]
def tracing_middleware(app): from elasticapm.contrib.aiohttp import CLIENT_KEY # noqa 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_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 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_transaction_outcome(http_status_code=500, 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() # decorating with @middleware is only required in aiohttp < 4.0, and we only support 3+ if aiohttp.__version__.startswith("3"): return middleware(handle_request) return handle_request
def use(self, middleware_handler): '''Add middleware to all request handlers.''' argnames = list(inspect.signature(middleware_handler).parameters) if argnames == ['request', 'handler']: # request middleware accepts (request, handler) arguments and returns response self.middlewares.append(web.middleware(middleware_handler)) elif argnames[0:1] == ['handler']: # handler middleware accepts (handler) argument and returns handler self.handler_middlewares.append(middleware_handler) self.update_handlers() self.update_options() else: raise ValueError('middleware_handler function signature must be (request, handler) or (handler)') return middleware_handler
def tracing_middleware(app): from elasticapm.contrib.aiohttp import CLIENT_KEY # noqa 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() # decorating with @middleware is only required in aiohttp < 4.0, and we only support 3+ if aiohttp.__version__.startswith("3"): return middleware(handle_request) return handle_request
def tracing_middleware(app, client=None): 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() # decorating with @middleware is only required in aiohttp < 4.0, and we only support 3+ if aiohttp.__version__.startswith("3"): return middleware(handle_request) return handle_request
def middleware(self, func): """Register given middleware (v1).""" self.middlewares.append(web.middleware(to_coroutine(func)))
def decorator(f: Func) -> Func: f.http_middleware_info = {"order": order} # type: ignore return web.middleware(f)
def _apply_middleware(original, middleware): return middleware(original)