From be1bdc77075cb3c2efdc27141e46cd33fffc0371 Mon Sep 17 00:00:00 2001 From: Richard Belleville Date: Thu, 28 Jan 2021 02:20:33 +0000 Subject: [PATCH] Report RPC statuses --- src/proto/grpc/testing/messages.proto | 25 ++++++++++++++++--- .../interop/xds_interop_client.py | 9 +++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/proto/grpc/testing/messages.proto b/src/proto/grpc/testing/messages.proto index 5acc2f0eadb..559876ed7c0 100644 --- a/src/proto/grpc/testing/messages.proto +++ b/src/proto/grpc/testing/messages.proto @@ -219,11 +219,27 @@ message LoadBalancerAccumulatedStatsRequest {} // Accumulated stats for RPCs sent by a test client. message LoadBalancerAccumulatedStatsResponse { // The total number of RPCs have ever issued for each type. - map num_rpcs_started_by_method = 1; + // Deprecated: use stats_per_method.rpcs_started instead. + map num_rpcs_started_by_method = 1 [deprecated = true]; // The total number of RPCs have ever completed successfully for each type. - map num_rpcs_succeeded_by_method = 2; + // Deprecated: use stats_per_method.result instead. + map num_rpcs_succeeded_by_method = 2 [deprecated = true]; // The total number of RPCs have ever failed for each type. - map num_rpcs_failed_by_method = 3; + // Deprecated: use stats_per_method.result instead. + map num_rpcs_failed_by_method = 3 [deprecated = true]; + + message MethodStats { + // The number of RPCs that were started for this method. + int32 rpcs_started = 1; + + // The number of RPCs that completed with each status for this method. The + // key is the integral value of a google.rpc.Code; the value is the count. + map result = 2; + } + + // Per-method RPC statistics. The key is the RpcType in string form; e.g. + // 'EMPTY_CALL' or 'UNARY_CALL' + map stats_per_method = 4; } // Configurations for a test client. @@ -245,6 +261,9 @@ message ClientConfigureRequest { repeated RpcType types = 1; // The collection of custom metadata to be attached to RPCs sent by the client. repeated Metadata metadata = 2; + // The deadline to use, in seconds, for all RPCs. If unset or zero, the + // client will use the default from the command-line. + int32 timeout_sec = 3; } // Response for updating a test client's configuration. diff --git a/src/python/grpcio_tests/tests_py3_only/interop/xds_interop_client.py b/src/python/grpcio_tests/tests_py3_only/interop/xds_interop_client.py index 138693890c6..640cb7dbd31 100644 --- a/src/python/grpcio_tests/tests_py3_only/interop/xds_interop_client.py +++ b/src/python/grpcio_tests/tests_py3_only/interop/xds_interop_client.py @@ -118,6 +118,9 @@ _global_rpcs_started: Mapping[str, int] = collections.defaultdict(int) _global_rpcs_succeeded: Mapping[str, int] = collections.defaultdict(int) _global_rpcs_failed: Mapping[str, int] = collections.defaultdict(int) +# Mapping[method, Mapping[status_code, count]] +_global_rpc_statuses: Mapping[str, Mapping[int, int]] = collections.defaultdict(lambda: collections.defaultdict(int)) + def _handle_sigint(sig, frame) -> None: _stop_event.set() @@ -163,6 +166,9 @@ class _LoadBalancerStatsServicer(test_pb2_grpc.LoadBalancerStatsServiceServicer caps_method] = _global_rpcs_succeeded[method] response.num_rpcs_failed_by_method[ caps_method] = _global_rpcs_failed[method] + response.stats_per_method[caps_method].rpcs_started = _global_rpcs_started[method] + for code, count in _global_rpc_statuses[method].items(): + response.stats_per_method[caps_method].result[code] = count logger.info("Returning cumulative stats response.") return response @@ -189,6 +195,7 @@ def _on_rpc_done(rpc_id: int, future: grpc.Future, method: str, print_response: bool) -> None: exception = future.exception() hostname = "" + _global_rpc_statuses[method][future.code().value[0]] += 1 if exception is not None: with _global_lock: _global_rpcs_failed[method] += 1 @@ -399,6 +406,8 @@ def parse_rpc_arg(rpc_arg: str) -> Sequence[str]: ", ".join(_SUPPORTED_METHODS))) return methods +resp = messages_pb2.LoadBalancerAccumulatedStatsResponse() +resp.stats_per_method["/method1"].result[2] = 11 if __name__ == "__main__": parser = argparse.ArgumentParser(