Exemple #1
0
def logStatus(e: grpc.RpcError) -> None:
    logging.info("----------------------------------")
    # logging.info("gRPC returned error: {}".format(e))
    # logging.info("  trailing_metadata:  {}".format(e.trailing_metadata()))
    print("----")
    code = e.code()
    print("  code:    {} ({})".format(code.name, code.value[0]))
    details = e.details()
    print("  details: {}".format(details))
    err_string = e.debug_error_string()
    print("  err str: {}".format(err_string))
    status = rpc_status.from_call(e)
    if status is not None:
        for detail in status.details:
            if detail.Is(error_details_pb2.ErrorInfo.DESCRIPTOR):
                errinfo = error_details_pb2.ErrorInfo()
                detail.Unpack(errinfo)
                print("  ErrorInfo:")
                print("    Reason: {}".format(errinfo.reason))
                print("    Domain: {}".format(errinfo.domain))
                print("    Metadata:")
                for k, v in errinfo.metadata.items():
                    print("      {}: {}".format(k, v))
                # logging.info("  ErrorInfo: {}".format(errinfo))
            else:
                print("  -- unknown details type.")
Exemple #2
0
def is_reset_signal(error: GoogleAPICallError) -> bool:
    """
    Determines whether the given error contains the stream RESET signal, sent by
    the server to instruct clients to reset stream state.

    Returns: True if the error contains the RESET signal.
    """
    if not is_retryable(error) or not error.response:
        return False
    try:
        status = rpc_status.from_call(error.response)
        if not status:
            return False
        for detail in status.details:
            if detail.Is(ErrorInfo.DESCRIPTOR):
                info = ErrorInfo()
                if (
                    detail.Unpack(info)
                    and info.reason == "RESET"
                    and info.domain == "pubsublite.googleapis.com"
                ):
                    return True
    except ValueError:
        pass
    return False
    def _missing_owner_rich_error(stub):
        logger.info("missing account owner, rich error")

        # open account request missing the owner
        cmd = OpenAccountRequest(balance=200)

        request = HandleCommandRequest(
            command=pack_any(cmd),
            prior_state=pack_any(Empty()),
            prior_event_meta=MetaData(),
        )

        did_fail = False

        try:
            stub.HandleCommand(request)
        except RpcError as e:
            error_status = rpc_status.from_call(e)
            assert error_status.details, 'missing details'
            bad_request = unpack_any(error_status.details[0], error_details_pb2.BadRequest)
            assert bad_request.field_violations, 'missing violations'
            violation = bad_request.field_violations[0]
            assert violation.field == "account_owner"
            assert violation.description == "missing account owner"
            did_fail = True

        assert did_fail, "did not fail"
Exemple #4
0
def _get_extra_data_from_error(error: RpcError):
    """
    Extra error info is stored in trailing_metadata as custom protos
    """
    status = rpc_status.from_call(error)

    if not status:
        return

    error_code = None
    field_errors = None
    for detail in status.details:
        # detail is an Any proto. Right now these are usually ErrorInfo protos.
        if detail.Is(ErrorInfo.DESCRIPTOR):
            error_info = ErrorInfo()
            detail.Unpack(error_info)
            error_code = error_info.code
        if detail.Is(BadRequest.DESCRIPTOR):
            bad_request = BadRequest()
            detail.Unpack(bad_request)
            field_errors = [
                FieldError(
                    field=field_error.field,
                    message=field_error.message,
                    code=field_error.code,
                ) for field_error in bad_request.field_errors
            ]

    return dict(
        error_code=error_code,
        field_errors=field_errors,
    )
Exemple #5
0
    def test_status_not_ok(self):
        with self.assertRaises(grpc.RpcError) as exception_context:
            self._channel.unary_unary(_STATUS_NOT_OK).with_call(_REQUEST)
        rpc_error = exception_context.exception

        self.assertEqual(rpc_error.code(), grpc.StatusCode.INTERNAL)
        # Failed RPC doesn't automatically generate status
        status = rpc_status.from_call(rpc_error)
        self.assertIs(status, None)
Exemple #6
0
def grpc_server_error(rpc_error):
    """
    A gRPC errors handler
    """
    app.rpc_token_metadata = None  # clear meta_data
    logger.error('gRPC error: %s' % str(rpc_error))
    err_name = rpc_error._state.code.name
    err_code = rpc_error._state.code.value[0]
    extended_status = rpc_status.from_call(rpc_error)
    return jsonify({'grpc_error': f'{err_name} {err_code} {extended_status}'}), HTTPStatus.CONFLICT
Exemple #7
0
def process(stub):
    try:
        response = stub.SayHello(helloworld_pb2.HelloRequest(name='Alice'))
        _LOGGER.info('Call success: %s', response.message)
    except grpc.RpcError as rpc_error:
        _LOGGER.error('Call failure: %s', rpc_error)
        status = rpc_status.from_call(rpc_error)
        for detail in status.details:
            if detail.Is(error_details_pb2.QuotaFailure.DESCRIPTOR):
                info = error_details_pb2.QuotaFailure()
                detail.Unpack(info)
                _LOGGER.error('Quota failure: %s', info)
            else:
                raise RuntimeError('Unexpected failure: %s' % detail)
Exemple #8
0
    def test_error_details(self):
        with self.assertRaises(grpc.RpcError) as exception_context:
            self._channel.unary_unary(_ERROR_DETAILS).with_call(_REQUEST)
        rpc_error = exception_context.exception

        status = rpc_status.from_call(rpc_error)
        self.assertEqual(rpc_error.code(), grpc.StatusCode.INTERNAL)
        self.assertEqual(status.code, code_pb2.Code.Value('INTERNAL'))

        # Check if the underlying proto message is intact
        self.assertEqual(
            status.details[0].Is(error_details_pb2.DebugInfo.DESCRIPTOR), True)
        info = error_details_pb2.DebugInfo()
        status.details[0].Unpack(info)
        self.assertIn('_error_details_unary_unary', info.stack_entries[-1])
Exemple #9
0
    def _missing_owner_rich_error(stub: BankAccountServiceStub):
        logger.info("missing account owner, rich error")
        # open account request missing the owner
        cmd = OpenAccountRequest(balance=200)
        did_fail = False
        try:
            stub.OpenAccount(cmd)
        except RpcError as e:
            error_status = rpc_status.from_call(e)
            assert error_status.details, 'missing details'
            bad_request = unpack_any(error_status.details[0],
                                     error_details_pb2.BadRequest)
            assert bad_request.field_violations, 'missing violations'
            violation = bad_request.field_violations[0]
            assert violation.field == "account_owner"
            assert violation.description == "missing account owner"
            did_fail = True

        assert did_fail, "did not fail"
Exemple #10
0
def dependency_error_details(exc, as_json=False):
    if not is_dependency(exc): return None
    # Should have dependency metadata.
    meta = exc.trailing_metadata()
    if not meta:
        return None
    status = rpc_status.from_call(exc)
    details = []
    for d in status.details:
        if not d.type_url.endswith('/proto.ModifyDep'):
            return None
        dep = entroq_pb2.ModifyDep()
        dep.ParseFromString(d.value)
        if dep.type == entroq_pb2.DETAIL and not dep.msg:
            continue
        if as_json:
            details.append(json_format.MessageToDict(dep))
        else:
            details.append(dep)
    return details
def handle_error(exc):
    """Parsers DebugInfo (https://github.com/googleapis/googleapis/blob/07244bb797ddd6e0c1c15b02b4467a9a5729299f/google/rpc/error_details.proto#L46-L52) from the trailing metadata of a grpc.RpcError

    Args:
        exc (grpc.RpcError): Exception to handle

    Raises: original exception or RemoteException

    """
    status = rpc_status.from_call(exc)
    if status is None:
        raise
    for detail in status.details:
        if detail.Is(error_details_pb2.DebugInfo.DESCRIPTOR):
            info = error_details_pb2.DebugInfo()
            detail.Unpack(info)
            remote_traceback = info.stack_entries
            remote_detail = info.detail
            raise RemoteException(remote_detail, remote_traceback) from exc
    raise
Exemple #12
0
    def _cos_process_command(cls, id, command, context):
        '''helper method to run process command'''
        logger.debug("begin process_command")
        client = cls._get_cos_client()
        command_any = pack_any(command)

        metadata = [('x-custom-request-uuid', str(uuid4()))]
        request = ProcessCommandRequest(entity_id=id, command=command_any)

        try:
            response = client.ProcessCommand(request=request, metadata=metadata)
            return cls._cos_unpack_state(response.state)
        except grpc.RpcError as e:
            output_status = rpc_status.from_call(e)

            if not output_status:
                context.abort(code=e.code(), details=e.details())

            context.abort_with_status(rpc_status.to_status(output_status))
        except Exception as e:
            context.abort(code=StatusCode.INTERNAL, details=str(e))
Exemple #13
0
def leaderboard():
    last_30_days = 'last_30_days' in request.args
    name = request.args.get('name')
    try:
        page = int(request.args.get('page', 0))
    except ValueError:
        return jsonify({'error': 'page value must be int'}), HTTPStatus.BAD_REQUEST

    with grpc.insecure_channel(config.GRPC_SERVER_HOST) as channel:
        stub = LeaderBoardStub(channel)
        rpc_request = GetLeaderBoard()
        if last_30_days:
            rpc_request.option = GetLeaderBoard.LAST_30_DAYS
        if page:
            rpc_request.page = page
        if name:
            rpc_request.name = name
        try:
            leaderboard_response = stub.GetLeaderBoardPages(rpc_request, metadata=[app.rpc_token_metadata])
            results = [(r.name, r.score, r.rank) for r in leaderboard_response.results]
            around_me = [(a.name, a.score, a.rank) for a in leaderboard_response.around_me]
        except grpc.RpcError as rpc_error:
            status = rpc_status.from_call(rpc_error)
            if status.code == code_pb2.INVALID_ARGUMENT and status.message == 'page':
                error, status = 'page value exceeds max possible value', HTTPStatus.BAD_REQUEST
            elif status.code == code_pb2.INVALID_ARGUMENT and status.message == 'name':
                if last_30_days:
                    error, status = 'player has no new results during last 30 days', HTTPStatus.BAD_REQUEST
                else:
                    error, status = 'unknown player name', HTTPStatus.BAD_REQUEST
            else:
                raise rpc_error
            return jsonify({'error': error}), status
        else:
            return jsonify({
                'next_page': leaderboard_response.next_page,
                'results': results,
                'around_me': around_me
            }), HTTPStatus.OK
Exemple #14
0
def _parse_grpc_error_details(rpc_exc):
    try:
        status = rpc_status.from_call(rpc_exc)
    except NotImplementedError:  # workaround
        return [], None

    if not status:
        return [], None

    possible_errors = [
        error_details_pb2.BadRequest,
        error_details_pb2.PreconditionFailure,
        error_details_pb2.QuotaFailure,
        error_details_pb2.ErrorInfo,
        error_details_pb2.RetryInfo,
        error_details_pb2.ResourceInfo,
        error_details_pb2.RequestInfo,
        error_details_pb2.DebugInfo,
        error_details_pb2.Help,
        error_details_pb2.LocalizedMessage,
    ]
    error_info = None
    error_details = []
    for detail in status.details:
        matched_detail_cls = list(
            filter(lambda x: detail.Is(x.DESCRIPTOR), possible_errors))
        # If nothing matched, use detail directly.
        if len(matched_detail_cls) == 0:
            info = detail
        else:
            info = matched_detail_cls[0]()
            detail.Unpack(info)
        error_details.append(info)
        if isinstance(info, error_details_pb2.ErrorInfo):
            error_info = info
    return error_details, error_info
Exemple #15
0
    def test_status_ok(self):
        _, call = self._channel.unary_unary(_STATUS_OK).with_call(_REQUEST)

        # Succeed RPC doesn't have status
        status = rpc_status.from_call(call)
        self.assertIs(status, None)
Exemple #16
0
datapoints = []
for x in range(0, 20):
    numeric_msg = math_pb2.Numeric()
    numeric_msg.value = random.uniform(0, 1)
    data_point = datapoint_pb2.Datapoint(
        stream="test.numeric", numeric=numeric_msg, timestamp=int(time.time() * 1000)
    )
    datapoints.append(data_point)
    # force some throttling errors to see error handling
    time.sleep(0.001)

request = agent_pb2.PostDataMultiRequest(datapoints=datapoints)

try:
    agent.PostDataMulti(request)
# catch rpcError
except grpc.RpcError as e:
    status = rpc_status.from_call(e)
    for post_data_multi_error in status.details:
        if post_data_multi_error.Is(agent_pb2.PostDataMultiError.DESCRIPTOR):
            # unpack error details into proto agent_pb2.PostDataMultiError
            post_data_multi_error_pb = agent_pb2.PostDataMultiError()
            post_data_multi_error.Unpack(post_data_multi_error_pb)
            for error in post_data_multi_error_pb.errors:
                # iterate through errors and check for retryable
                if error.retryable:
                    print("datapoint at index %s is retryable" % error.index)
                else:
                    print("datapoint at index %s is not retryable" % error.index)