aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/grpc++/impl/codegen/call.h2
-rw-r--r--include/grpc/impl/codegen/grpc_types.h1
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.cc9
-rw-r--r--src/core/lib/channel/channel_stack.h1
-rw-r--r--src/core/lib/surface/call.cc34
-rw-r--r--src/core/lib/transport/error_utils.cc8
-rw-r--r--src/core/lib/transport/error_utils.h8
-rw-r--r--test/cpp/microbenchmarks/bm_error.cc6
8 files changed, 43 insertions, 26 deletions
diff --git a/include/grpc++/impl/codegen/call.h b/include/grpc++/impl/codegen/call.h
index 1a988297dc..91f45b3147 100644
--- a/include/grpc++/impl/codegen/call.h
+++ b/include/grpc++/impl/codegen/call.h
@@ -579,6 +579,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 = &error_string_;
op->flags = 0;
op->reserved = NULL;
}
@@ -605,6 +606,7 @@ class CallOpClientRecvStatus {
Status* recv_status_;
grpc_status_code status_code_;
grpc_slice error_message_;
+ const char* error_string_;
};
/// An abstract collection of call ops, used to generate the
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index 03be610d25..83b35b1dc4 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -558,6 +558,7 @@ typedef struct grpc_op {
grpc_metadata_array* trailing_metadata;
grpc_status_code* status;
grpc_slice* status_details;
+ const char** error_string;
} recv_status_on_client;
struct grpc_op_recv_close_on_server {
/** out argument, set to 1 if the call failed in any way (seen as a
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
index 034e6ed8ca..d5c61d80ae 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
@@ -1756,7 +1756,7 @@ static void send_goaway(grpc_exec_ctx* exec_ctx, grpc_chttp2_transport* t,
grpc_http2_error_code http_error;
grpc_slice slice;
grpc_error_get_status(exec_ctx, error, GRPC_MILLIS_INF_FUTURE, NULL, &slice,
- &http_error);
+ &http_error, NULL);
grpc_chttp2_goaway_append(t->last_new_stream_id, (uint32_t)http_error,
grpc_slice_ref_internal(slice), &t->qbuf);
grpc_chttp2_initiate_write(exec_ctx, t,
@@ -2059,7 +2059,7 @@ void grpc_chttp2_cancel_stream(grpc_exec_ctx* exec_ctx,
if (s->id != 0) {
grpc_http2_error_code http_error;
grpc_error_get_status(exec_ctx, due_to_error, s->deadline, NULL, NULL,
- &http_error);
+ &http_error, NULL);
grpc_slice_buffer_add(
&t->qbuf, grpc_chttp2_rst_stream_create(s->id, (uint32_t)http_error,
&s->stats.outgoing));
@@ -2077,7 +2077,8 @@ void grpc_chttp2_fake_status(grpc_exec_ctx* exec_ctx, grpc_chttp2_transport* t,
grpc_chttp2_stream* s, grpc_error* error) {
grpc_status_code status;
grpc_slice slice;
- grpc_error_get_status(exec_ctx, error, s->deadline, &status, &slice, NULL);
+ grpc_error_get_status(exec_ctx, error, s->deadline, &status, &slice, NULL,
+ NULL);
if (status != GRPC_STATUS_OK) {
s->seen_error = true;
@@ -2243,7 +2244,7 @@ static void close_from_api(grpc_exec_ctx* exec_ctx, grpc_chttp2_transport* t,
grpc_status_code grpc_status;
grpc_slice slice;
grpc_error_get_status(exec_ctx, error, s->deadline, &grpc_status, &slice,
- NULL);
+ NULL, NULL);
GPR_ASSERT(grpc_status >= 0 && (int)grpc_status < 100);
diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h
index aa993112a0..41851382ae 100644
--- a/src/core/lib/channel/channel_stack.h
+++ b/src/core/lib/channel/channel_stack.h
@@ -84,6 +84,7 @@ typedef struct {
typedef struct {
grpc_call_stats stats;
grpc_status_code final_status;
+ const char* error_string;
} grpc_call_final_info;
/* Channel filters specify:
diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc
index 9fd4fdbef9..4ce494872a 100644
--- a/src/core/lib/surface/call.cc
+++ b/src/core/lib/surface/call.cc
@@ -234,6 +234,7 @@ struct grpc_call {
struct {
grpc_status_code* status;
grpc_slice* status_details;
+ const char** error_string;
} client;
struct {
int* cancelled;
@@ -286,7 +287,8 @@ static void receiving_slice_ready(grpc_exec_ctx* exec_ctx, void* bctlp,
static void get_final_status(grpc_exec_ctx* exec_ctx, grpc_call* call,
void (*set_value)(grpc_status_code code,
void* user_data),
- void* set_value_user_data, grpc_slice* details);
+ void* set_value_user_data, grpc_slice* details,
+ const char** error_string);
static void set_status_value_directly(grpc_status_code status, void* dest);
static void set_status_from_error(grpc_exec_ctx* exec_ctx, grpc_call* call,
status_source source, grpc_error* error);
@@ -548,7 +550,8 @@ static void destroy_call(grpc_exec_ctx* exec_ctx, void* call,
}
get_final_status(exec_ctx, c, set_status_value_directly,
- &c->final_info.final_status, NULL);
+ &c->final_info.final_status, NULL,
+ &c->final_info.error_string);
c->final_info.stats.latency =
gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time);
@@ -734,16 +737,15 @@ static void cancel_with_status(grpc_exec_ctx* exec_ctx, grpc_call* c,
* FINAL STATUS CODE MANIPULATION
*/
-static bool get_final_status_from(grpc_exec_ctx* exec_ctx, grpc_call* call,
- grpc_error* error, bool allow_ok_status,
- void (*set_value)(grpc_status_code code,
- void* user_data),
- void* set_value_user_data,
- grpc_slice* details) {
+static bool get_final_status_from(
+ grpc_exec_ctx* exec_ctx, grpc_call* call, grpc_error* error,
+ bool allow_ok_status,
+ void (*set_value)(grpc_status_code code, void* user_data),
+ void* set_value_user_data, grpc_slice* details, const char** error_string) {
grpc_status_code code;
grpc_slice slice = grpc_empty_slice();
grpc_error_get_status(exec_ctx, error, call->send_deadline, &code, &slice,
- NULL);
+ NULL, error_string);
if (code == GRPC_STATUS_OK && !allow_ok_status) {
return false;
}
@@ -758,7 +760,8 @@ static bool get_final_status_from(grpc_exec_ctx* exec_ctx, grpc_call* call,
static void get_final_status(grpc_exec_ctx* exec_ctx, grpc_call* call,
void (*set_value)(grpc_status_code code,
void* user_data),
- void* set_value_user_data, grpc_slice* details) {
+ void* set_value_user_data, grpc_slice* details,
+ const char** error_string) {
int i;
received_status status[STATUS_SOURCE_COUNT];
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
@@ -782,7 +785,7 @@ static void get_final_status(grpc_exec_ctx* exec_ctx, grpc_call* call,
grpc_error_has_clear_grpc_status(status[i].error)) {
if (get_final_status_from(exec_ctx, call, status[i].error,
allow_ok_status != 0, set_value,
- set_value_user_data, details)) {
+ set_value_user_data, details, error_string)) {
return;
}
}
@@ -792,7 +795,7 @@ static void get_final_status(grpc_exec_ctx* exec_ctx, grpc_call* call,
if (status[i].is_set) {
if (get_final_status_from(exec_ctx, call, status[i].error,
allow_ok_status != 0, set_value,
- set_value_user_data, details)) {
+ set_value_user_data, details, error_string)) {
return;
}
}
@@ -1333,10 +1336,11 @@ static void post_batch_completion(grpc_exec_ctx* exec_ctx,
if (call->is_client) {
get_final_status(exec_ctx, call, set_status_value_directly,
call->final_op.client.status,
- call->final_op.client.status_details);
+ call->final_op.client.status_details,
+ call->final_op.client.error_string);
} else {
get_final_status(exec_ctx, call, set_cancelled_value,
- call->final_op.server.cancelled, NULL);
+ call->final_op.server.cancelled, NULL, NULL);
}
GRPC_ERROR_UNREF(error);
@@ -1993,6 +1997,8 @@ static grpc_call_error call_start_batch(grpc_exec_ctx* exec_ctx,
call->final_op.client.status = op->data.recv_status_on_client.status;
call->final_op.client.status_details =
op->data.recv_status_on_client.status_details;
+ call->final_op.client.error_string =
+ op->data.recv_status_on_client.error_string;
stream_op->recv_trailing_metadata = true;
stream_op->collect_stats = true;
stream_op_payload->recv_trailing_metadata.recv_trailing_metadata =
diff --git a/src/core/lib/transport/error_utils.cc b/src/core/lib/transport/error_utils.cc
index d968b04fd8..15f9875270 100644
--- a/src/core/lib/transport/error_utils.cc
+++ b/src/core/lib/transport/error_utils.cc
@@ -41,8 +41,12 @@ static grpc_error* recursively_find_error_with_field(grpc_error* error,
void grpc_error_get_status(grpc_exec_ctx* exec_ctx, grpc_error* error,
grpc_millis deadline, grpc_status_code* code,
- grpc_slice* slice,
- grpc_http2_error_code* http_error) {
+ grpc_slice* slice, grpc_http2_error_code* http_error,
+ const char** full_error_details) {
+ if (full_error_details != NULL) {
+ *full_error_details = grpc_error_string(error);
+ }
+
// Start with the parent error and recurse through the tree of children
// until we find the first one that has a status code.
grpc_error* found_error =
diff --git a/src/core/lib/transport/error_utils.h b/src/core/lib/transport/error_utils.h
index 690e42058a..d47c4f2a3b 100644
--- a/src/core/lib/transport/error_utils.h
+++ b/src/core/lib/transport/error_utils.h
@@ -30,13 +30,15 @@ extern "C" {
/// A utility function to get the status code and message to be returned
/// to the application. If not set in the top-level message, looks
/// through child errors until it finds the first one with these attributes.
-/// All attributes are pulled from the same child error. If any of the
-/// attributes (code, msg, http_status) are unneeded, they can be passed as
+/// All attributes are pulled from the same child error. full_error_details will
+/// be populated with the entire error string. If any of the attributes (code,
+/// msg, http_status, full_error_details) are unneeded, they can be passed as
/// NULL.
void grpc_error_get_status(grpc_exec_ctx* exec_ctx, grpc_error* error,
grpc_millis deadline, grpc_status_code* code,
grpc_slice* slice,
- grpc_http2_error_code* http_status);
+ grpc_http2_error_code* http_status,
+ const char** full_error_details);
/// A utility function to check whether there is a clear status code that
/// doesn't need to be guessed in \a error. This means that \a error or some
diff --git a/test/cpp/microbenchmarks/bm_error.cc b/test/cpp/microbenchmarks/bm_error.cc
index 56b80dfcf6..955cdf5a17 100644
--- a/test/cpp/microbenchmarks/bm_error.cc
+++ b/test/cpp/microbenchmarks/bm_error.cc
@@ -253,7 +253,7 @@ static void BM_ErrorGetStatus(benchmark::State& state) {
grpc_status_code status;
grpc_slice slice;
grpc_error_get_status(&exec_ctx, fixture.error(), fixture.deadline(),
- &status, &slice, NULL);
+ &status, &slice, NULL, NULL);
}
grpc_exec_ctx_finish(&exec_ctx);
track_counters.Finish(state);
@@ -267,7 +267,7 @@ static void BM_ErrorGetStatusCode(benchmark::State& state) {
while (state.KeepRunning()) {
grpc_status_code status;
grpc_error_get_status(&exec_ctx, fixture.error(), fixture.deadline(),
- &status, NULL, NULL);
+ &status, NULL, NULL, NULL);
}
grpc_exec_ctx_finish(&exec_ctx);
track_counters.Finish(state);
@@ -281,7 +281,7 @@ static void BM_ErrorHttpError(benchmark::State& state) {
while (state.KeepRunning()) {
grpc_http2_error_code error;
grpc_error_get_status(&exec_ctx, fixture.error(), fixture.deadline(), NULL,
- NULL, &error);
+ NULL, &error, NULL);
}
grpc_exec_ctx_finish(&exec_ctx);
track_counters.Finish(state);