Merge pull request #13364 from ncteisen/surfacing-error-details

Add Error String to Recv Status API
pull/13288/head
Noah Eisen 7 years ago committed by GitHub
commit dd010f2297
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      include/grpc++/impl/codegen/call.h
  2. 4
      include/grpc/impl/codegen/grpc_types.h
  3. 9
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  4. 1
      src/core/lib/channel/channel_stack.h
  5. 34
      src/core/lib/surface/call.cc
  6. 9
      src/core/lib/transport/error_utils.cc
  7. 8
      src/core/lib/transport/error_utils.h
  8. 6
      test/cpp/microbenchmarks/bm_error.cc

@ -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 = nullptr;
op->flags = 0;
op->reserved = NULL;
}

@ -558,6 +558,10 @@ typedef struct grpc_op {
grpc_metadata_array* trailing_metadata;
grpc_status_code* status;
grpc_slice* status_details;
/** If this is not nullptr, it will be populated with the full fidelity
* error string for debugging purposes. The application is responsible
* for freeing the data. */
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

@ -1758,7 +1758,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, nullptr,
&slice, &http_error);
&slice, &http_error, nullptr);
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,
@ -2061,7 +2061,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, nullptr,
nullptr, &http_error);
nullptr, &http_error, nullptr);
grpc_slice_buffer_add(
&t->qbuf, grpc_chttp2_rst_stream_create(s->id, (uint32_t)http_error,
&s->stats.outgoing));
@ -2079,7 +2079,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, nullptr);
grpc_error_get_status(exec_ctx, error, s->deadline, &status, &slice, nullptr,
nullptr);
if (status != GRPC_STATUS_OK) {
s->seen_error = true;
}
@ -2244,7 +2245,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,
nullptr);
nullptr, nullptr);
GPR_ASSERT(grpc_status >= 0 && (int)grpc_status < 100);

@ -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:

@ -234,6 +234,7 @@ struct grpc_call {
struct {
grpc_status_code* status;
grpc_slice* status_details;
const char** error_string;
} client;
struct {
int* cancelled;
@ -284,7 +285,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);
@ -546,7 +548,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, nullptr);
&c->final_info.final_status, nullptr,
c->final_info.error_string);
c->final_info.stats.latency =
gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time);
@ -733,16 +736,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,
nullptr);
nullptr, error_string);
if (code == GRPC_STATUS_OK && !allow_ok_status) {
return false;
}
@ -757,7 +759,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++) {
@ -781,7 +784,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;
}
}
@ -791,7 +794,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;
}
}
@ -1332,10 +1335,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, nullptr);
call->final_op.server.cancelled, nullptr, nullptr);
}
GRPC_ERROR_UNREF(error);
@ -1992,6 +1996,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 =

@ -18,6 +18,7 @@
#include "src/core/lib/transport/error_utils.h"
#include <grpc/support/string_util.h>
#include "src/core/lib/iomgr/error_internal.h"
#include "src/core/lib/transport/status_conversion.h"
@ -41,8 +42,8 @@ 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** error_string) {
// 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 =
@ -69,6 +70,10 @@ void grpc_error_get_status(grpc_exec_ctx* exec_ctx, grpc_error* error,
}
if (code != nullptr) *code = status;
if (error_string != NULL && status != GRPC_STATUS_OK) {
*error_string = gpr_strdup(grpc_error_string(error));
}
if (http_error != nullptr) {
if (grpc_error_get_int(found_error, GRPC_ERROR_INT_HTTP2_ERROR, &integer)) {
*http_error = (grpc_http2_error_code)integer;

@ -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. error_string will
/// be populated with the entire error string. If any of the attributes (code,
/// msg, http_status, error_string) 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** error_string);
/// 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

@ -251,7 +251,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, nullptr);
&status, &slice, nullptr, nullptr);
}
grpc_exec_ctx_finish(&exec_ctx);
track_counters.Finish(state);
@ -265,7 +265,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, nullptr, nullptr);
&status, nullptr, nullptr, nullptr);
}
grpc_exec_ctx_finish(&exec_ctx);
track_counters.Finish(state);
@ -279,7 +279,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(),
nullptr, nullptr, &error);
nullptr, nullptr, &error, nullptr);
}
grpc_exec_ctx_finish(&exec_ctx);
track_counters.Finish(state);

Loading…
Cancel
Save