diff options
-rw-r--r-- | include/grpc++/impl/codegen/call.h | 15 | ||||
-rw-r--r-- | include/grpc++/impl/codegen/client_context.h | 14 | ||||
-rw-r--r-- | test/cpp/end2end/end2end_test.cc | 8 |
3 files changed, 34 insertions, 3 deletions
diff --git a/include/grpc++/impl/codegen/call.h b/include/grpc++/impl/codegen/call.h index af2c2b510c..e581049e7f 100644 --- a/include/grpc++/impl/codegen/call.h +++ b/include/grpc++/impl/codegen/call.h @@ -558,10 +558,12 @@ class CallOpRecvInitialMetadata { class CallOpClientRecvStatus { public: - CallOpClientRecvStatus() : recv_status_(nullptr) {} + CallOpClientRecvStatus() + : recv_status_(nullptr), debug_error_string_(nullptr) {} void ClientRecvStatus(ClientContext* context, Status* status) { - metadata_map_ = &context->trailing_metadata_; + client_context_ = context; + metadata_map_ = &client_context_->trailing_metadata_; recv_status_ = status; error_message_ = g_core_codegen_interface->grpc_empty_slice(); } @@ -574,7 +576,7 @@ class CallOpClientRecvStatus { op->data.recv_status_on_client.trailing_metadata = metadata_map_->arr(); op->data.recv_status_on_client.status = &status_code_; op->data.recv_status_on_client.status_details = &error_message_; - op->data.recv_status_on_client.error_string = nullptr; + op->data.recv_status_on_client.error_string = &debug_error_string_; op->flags = 0; op->reserved = NULL; } @@ -592,13 +594,20 @@ class CallOpClientRecvStatus { grpc::string(GRPC_SLICE_START_PTR(error_message_), GRPC_SLICE_END_PTR(error_message_)), binary_error_details); + client_context_->set_debug_error_string( + debug_error_string_ != nullptr ? debug_error_string_ : ""); g_core_codegen_interface->grpc_slice_unref(error_message_); + if (debug_error_string_ != nullptr) { + g_core_codegen_interface->gpr_free((void*)debug_error_string_); + } recv_status_ = nullptr; } private: + ClientContext* client_context_; MetadataMap* metadata_map_; Status* recv_status_; + const char* debug_error_string_; grpc_status_code status_code_; grpc_slice error_message_; }; diff --git a/include/grpc++/impl/codegen/client_context.h b/include/grpc++/impl/codegen/client_context.h index 22b581cbc5..61d97ce818 100644 --- a/include/grpc++/impl/codegen/client_context.h +++ b/include/grpc++/impl/codegen/client_context.h @@ -348,6 +348,13 @@ class ClientContext { /// Applications never need to call this method. grpc_call* c_call() { return call_; } + /// EXPERIMENTAL debugging API + /// + /// if status is not ok() for an RPC, this will return a detailed string + /// of the gRPC Core error that led to the failure. It should not be relied + /// upon for anything other than gaining more debug data in failure cases. + grpc::string debug_error_string() const { return debug_error_string_; } + private: // Disallow copy and assign. ClientContext(const ClientContext&); @@ -374,6 +381,11 @@ class ClientContext { template <class InputMessage, class OutputMessage> friend class ::grpc::internal::BlockingUnaryCallImpl; + // Used by friend class CallOpClientRecvStatus + void set_debug_error_string(const grpc::string& debug_error_string) { + debug_error_string_ = debug_error_string; + } + grpc_call* call() const { return call_; } void set_call(grpc_call* call, const std::shared_ptr<Channel>& channel); @@ -412,6 +424,8 @@ class ClientContext { grpc_compression_algorithm compression_algorithm_; bool initial_metadata_corked_; + + grpc::string debug_error_string_; }; } // namespace grpc diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index c71034bbe8..1d63f395dc 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -741,6 +741,7 @@ TEST_P(End2endTest, RequestStreamOneRequest) { Status s = stream->Finish(); EXPECT_EQ(response.message(), request.message()); EXPECT_TRUE(s.ok()); + EXPECT_TRUE(context.debug_error_string().empty()); } TEST_P(End2endTest, RequestStreamOneRequestWithCoalescingApi) { @@ -1258,6 +1259,13 @@ TEST_P(End2endTest, ExpectErrorTest) { EXPECT_EQ(iter->code(), s.error_code()); EXPECT_EQ(iter->error_message(), s.error_message()); EXPECT_EQ(iter->binary_error_details(), s.error_details()); + EXPECT_TRUE(context.debug_error_string().find("created") != + std::string::npos); + EXPECT_TRUE(context.debug_error_string().find("file") != std::string::npos); + EXPECT_TRUE(context.debug_error_string().find("line") != std::string::npos); + EXPECT_TRUE(context.debug_error_string().find("status") != + std::string::npos); + EXPECT_TRUE(context.debug_error_string().find("13") != std::string::npos); } } |