Exemple #1
0
    async def rpc_handler(self, request: web.Request) -> web.Response:
        try:
            result = await self._rpc.call(
                await request.read(), request.charset
            )
            if result.method is not None:
                span.tag(SPAN_TAG_RPC_METHOD, result.method)

            if result.error is not None:
                span.error(result.error)
                if isinstance(result.error, InternalError):
                    self.app.log_err(result.error)
                resp = self._err_resp(result.error)
                if result.result is not None:
                    resp['result'] = result.result

            else:
                resp = {"code": 0, "message": 'OK', 'result': result.result}

            span.tag(SPAN_TAG_RPC_CODE, resp['code'])
            span.name = 'rpc::in (%s)' % result.method
            span.set_name4adapter(self.app.logger.ADAPTER_PROMETHEUS, 'rpc_in')

            body = self._json_encode(resp).encode()

            return web.Response(body=body, content_type='application/json')
        except Exception as err:
            span.error(err)
            self.app.log_err(err)
            return web.Response(
                body=self._json_encode(
                    self._err_resp(InternalError(parent=err))
                ).encode(),
                content_type='application/json',
            )
Exemple #2
0
 def _set_span_method(self, method: Optional[str]) -> None:
     if not span:
         return
     if method is not None:
         span.name = 'rpc::in (%s)' % method
         span.tag(SPAN_TAG_JSONRPC_METHOD, method)
     else:
         span.name = 'rpc::in::error'
Exemple #3
0
 async def _exec_in_executor(self, method: str, kwargs: Dict[str,
                                                             Any]) -> Any:
     try:
         return await self._ex.exec(name=method, args=None, kwargs=kwargs)
     except Exception as err:
         if app and span and hasattr(err, 'code'):
             span.tag(SPAN_TAG_RPC_CODE, getattr(err, 'code'))
         raise
Exemple #4
0
 async def _exec_in_executor(self, method: str, args: Tuple[Any, ...],
                             kwargs: Dict[str, Any]) -> Any:
     try:
         if self._discover_enabled and method == 'rpc.discover':
             if len(args) or len(kwargs):
                 raise _InvalidArguments()
             return self._discover()
         return await self._ex.exec(method, args, kwargs)
     except Exception as err:
         if app and span and hasattr(err, 'jsonrpc_error_code'):
             span.tag(SPAN_TAG_RPC_CODE, getattr(err, 'jsonrpc_error_code'))
         raise
Exemple #5
0
    async def __call__(
        self,
        scope: dict,
        receive: Callable[..., Awaitable],
        send: Callable[..., Awaitable],
    ) -> None:
        span_token: Optional[Token] = None

        headers: Dict[str, str] = {}
        url: Optional[URL] = None
        host: Optional[str] = None
        method: Optional[str] = None
        path: Optional[str] = None
        if scope['type'] == 'http':
            headers = {h[0].decode(): h[1].decode() for h in scope['headers']}
            host = ':'.join([str(s) for s in scope['server']])
            path = scope['raw_path'].decode()
            if scope['query_string']:
                path += '?' + scope['query_string'].decode()
            url = URL('%s://%s%s' % (scope['scheme'], host, path))
        try:
            span: HttpSpan = self.uvicorn.app.logger.span_from_headers(  # type: ignore
                headers, cls=ServerHttpSpan
            )
            span.name, span_tags = self._get_route_details(scope)
            for tag_name, tag_value in span_tags.items():
                span.tag(tag_name, tag_value)
            span_token = ctx_span_set(span)
            with span:
                span.kind = HttpSpan.KIND_SERVER
                if host is not None:
                    span.tag(HttpSpan.TAG_HTTP_HOST, host)
                if path is not None:
                    span.tag(HttpSpan.TAG_HTTP_PATH, path)
                if method is not None:
                    span.tag(HttpSpan.TAG_HTTP_METHOD, method)
                if url is not None:
                    span.tag(HttpSpan.TAG_HTTP_URL, self._mask_url(url))
                try:
                    await self.app(
                        scope,
                        partial(self.receive_wraper, receive),
                        partial(self.send_wraper, send),
                    )
                except Exception as err:
                    self.uvicorn.app.log_err(err)
                    span.error(err)
        except Exception as err:
            self.uvicorn.app.log_err(err)
            raise
        finally:
            if span_token:
                ctx_span_reset(span_token)
Exemple #6
0
    async def _exec_batch(
        self, req: rpc.JSONRPCBatchRequest
    ) -> Optional[rpc.RPCBatchResponse]:
        if span:
            span.name = 'rpc::in::batch'
            span.tag(SPAN_TAG_JSONRPC_IS_BATCH, 'true')
            span.set_name4adapter(
                self._app.logger.ADAPTER_PROMETHEUS, 'rpc_in_batch'
            )

        resp = req.create_batch_response()
        batch = []

        for req_item in req:
            if isinstance(req_item, rpc.InvalidRequestError):
                batch.append(self._exec_err(req_item))
            else:
                batch.append(
                    self._exec(
                        req_item.method,
                        req_item.args,
                        req_item.kwargs,
                        req_item.one_way,
                    )
                )

        results = await asyncio.gather(*batch, return_exceptions=True)

        if resp is None:
            return None

        for i in range(len(req)):
            if isinstance(req[i], rpc.InvalidRequestError):
                err_resp = req[i].error_respond()
                if hasattr(err_resp, 'data'):
                    err_resp.data = self.cast2dump(err_resp.data)
                resp.append(err_resp)
            elif req[i].one_way:
                pass
            elif isinstance(results[i], BaseException):
                err_resp = req[i].error_respond(results[i])
                if hasattr(err_resp, 'data'):
                    err_resp.data = self.cast2dump(err_resp.data)
                resp.append(err_resp)
            else:
                resp.append(req[i].respond(self.cast2dump(results[i])))

        return resp
Exemple #7
0
 def _set_span_err(self, err: Exception) -> None:
     if not span:
         return
     span.tag('error', 'true')
     span.annotate(span.ANN_TRACEBACK, traceback.format_exc())
     if hasattr(err, 'jsonrpc_error_code'):
         span.tag(
             SPAN_TAG_JSONRPC_CODE,
             str(err.jsonrpc_error_code),  # type: ignore
         )
     else:
         code, _, _ = _get_code_message_and_data(err)
         span.tag(SPAN_TAG_JSONRPC_CODE, str(code))
Exemple #8
0
    async def _exec(self, parent_trace_id: str, task: Task) -> None:
        with wrap2span(
                name=TaskManagerSpan.NAME_EXEC,
                kind=Span.KIND_SERVER,
                ignore_ctx=True,
                cls=TaskManagerSpan,
                app=self.app,
        ) as span:
            if task.trace_id is not None:
                span.trace_id = task.trace_id
                span.parent_id = task.trace_span_id

            if self._db is None or self._executor is None:  # pragma: no cover
                raise UserWarning

            span.name = '%s::%s' % (TaskManagerSpan.NAME_EXEC, task.name)
            span.tag(TaskManagerSpan.TAG_PARENT_TRACE_ID, parent_trace_id)
            span.tag(TaskManagerSpan.TAG_TASK_ID, task.id)
            span.tag(TaskManagerSpan.TAG_TASK_NAME, task.name)
            try:
                err: Optional[Exception] = None
                err_str: Optional[str] = None
                err_trace: Optional[str] = None
                res: Any = None
                time_begin = time.time()
                try:
                    res = await self._executor.exec(task.name,
                                                    kwargs=task.params)
                except Exception as e:
                    err = e
                    if isinstance(err, Retry):
                        err_str = str(err.err)
                    else:
                        err_str = str(err)
                    err_trace = traceback.format_exc()
                    span.error(err)
                    self.app.log_err(err)
                time_finish = time.time()

                await self._db.task_log_add(
                    task.id,
                    task.eta,
                    time_begin,
                    time_finish,
                    res,
                    err_str,
                    err_trace,
                    lock=True,
                )

                if task.retries is None:
                    retries = 0
                else:
                    retries = task.retries + 1

                if err is not None:
                    if isinstance(err, Retry):
                        if retries >= task.max_retries:
                            await self._db.task_move_arch(
                                task.id,
                                STATUS_ERROR,
                                retries,
                                lock=True,
                                with_trace_id=task.trace_id is not None,
                            )
                        else:
                            await self._db.task_retry(
                                task.id,
                                retries,
                                task.retry_delay.total_seconds(),
                                lock=True,
                            )
                    else:
                        await self._db.task_move_arch(
                            task.id,
                            STATUS_ERROR,
                            retries,
                            lock=True,
                            with_trace_id=task.trace_id is not None,
                        )
                else:
                    await self._db.task_move_arch(
                        task.id,
                        STATUS_SUCCESSFUL,
                        retries,
                        lock=True,
                        with_trace_id=task.trace_id is not None,
                    )
            except Exception as err:
                span.error(err)
                self.app.log_err(err)
                raise