def timeit_task( self, coro: Awaitable[_T], name: typedefs.MName, *, tags: Optional[typedefs.MTags] = None, sample_rate: Optional[typedefs.MSampleRate] = None, threshold_ms: Optional[typedefs.MValue] = None, ) -> "asyncio.Task[_T]": """ Creates a task and returns it, adds a done callback for sending time metric when done and if exceeds threshold. """ loop = get_event_loop() started_at = loop.time() def _callback(_: Any) -> None: duration = (loop.time() - started_at) * 1000 if threshold_ms and duration < threshold_ms: return self.timing(name, value=int(duration), tags=tags, sample_rate=sample_rate) task = loop.create_task(coro) task.add_done_callback(_callback) return task
async def connect(self) -> None: loop = get_event_loop() await loop.create_datagram_endpoint(lambda: self._protocol, remote_addr=(self._host, self._port)) self._listen_future = asyncio.ensure_future(self._listen())
async def middleware( request: web.Request, handler: _THandler ) -> web.StreamResponse: loop = get_event_loop() request_started_at = loop.time() # By default response status is 500 because we don't want to write any logic for # catching exceptions except exceptions which inherited from # `web.HTTPException`. And also we will override response status in case of any # successful handler execution. response_status = cast(int, HTTPStatus.INTERNAL_SERVER_ERROR.value) try: response = await handler(request) response_status = response.status except web.HTTPException as e: response_status = e.status raise e finally: if _proceed_collecting( # pragma: no branch request, response_status, collect_not_allowed, collect_not_found ): request_duration = (loop.time() - request_started_at) * 1000 request.app[client_app_key].timing( # pragma: no branch request_duration_metric_name, value=request_duration, tags={ "method": request.method, "path": _derive_request_path(request), "status": response_status, }, ) return response
async def middleware(request: web.Request, handler: _SimpleHandler) -> web.StreamResponse: loop = get_event_loop() request_started_at = loop.time() try: response = await handler(request) response_status = response.status except web.HTTPException as e: response_status = e.status raise e except Exception as e: response_status = HTTPStatus.INTERNAL_SERVER_ERROR.value raise e finally: if _proceed_collecting( # pragma: no branch request, response_status, collect_not_allowed, collect_not_found): request_duration = loop.time() - request_started_at request.app[client_app_key].timing( request_duration_metric_name, value=request_duration, tags={ "method": request.method, "path": request.path, "status": response_status, }, ) return response
async def connect(self) -> None: loop = get_event_loop() await loop.create_datagram_endpoint(lambda: self._protocol, remote_addr=(self._host, self._port)) self._pending_queue = asyncio.Queue(maxsize=self._pending_queue_size) self._listen_future = asyncio.ensure_future(self._listen()) self._listen_future_join = asyncio.Future() self._state = typedefs.CState.CONNECTED
async def middleware_response(request: Request, response: HTTPResponse) -> None: if _proceed_collecting(request, response, collect_not_allowed, collect_not_found): request_duration = (get_event_loop().time() - request["_statsd_request_started_at"]) getattr(request.app, client_app_key).timing( request_duration_metric_name, value=request_duration, tags={ "method": request.method, "path": request.path, "status": response.status, }, )
async def dispatch( self, request: Request, call_next: Callable[[Request], Awaitable[Response]]) -> Response: loop = get_event_loop() request_started_at = loop.time() # By default response status is 500 because we don't want to write any logic for # catching exceptions except exceptions which inherited from `HTTPException`. # And also we will override response status in case of any successful handler # execution. response_status = cast(int, HTTPStatus.INTERNAL_SERVER_ERROR.value) try: response = await call_next(request) response_status = response.status_code except HTTPException as e: # pragma: no cover # We kept exception handling here (just in case), but code looks useless. # We're unable to cover that part of code with tests because the framework # handles exceptions somehow different, somehow deeply inside. response_status = e.status_code raise e finally: request_path, request_path_template = _derive_request_path(request) if _proceed_collecting( # pragma: no branch request_path_template, response_status, self._collect_not_allowed, self._collect_not_found, ): request_duration = (loop.time() - request_started_at) * 1000 self._client.timing( # pragma: no branch self._request_duration_metric_name, value=request_duration, tags={ "method": request.method, "path": request_path_template or request_path, "status": response_status, }, ) return response
def timeit( self, name: typedefs.MName, *, tags: Optional[typedefs.MTags] = None, sample_rate: Optional[typedefs.MSampleRate] = None, threshold_ms: Optional[typedefs.MValue] = None, ) -> Iterator[None]: """ Context manager for easily timing methods. """ loop = get_event_loop() started_at = loop.time() try: yield finally: value = (loop.time() - started_at) * 1000 if not threshold_ms or value > threshold_ms: self.timing(name, value=int(value), tags=tags, sample_rate=sample_rate)
async def middleware_request(request: Request) -> None: request["_statsd_request_started_at"] = get_event_loop().time()