ugrpc::RichStatus is a userver wrapper around google::rpc::Status that provides a convenient API for creating and managing gRPC status responses with rich error details. It follows the Google AIP-193 standard for structured error reporting, allowing services to provide detailed error information that clients can use for better error handling and user experience.
Introduction to RichStatus
ugrpc::RichStatus allows you to create gRPC status responses with structured error information conforming to the Google RPC error model. It supports adding multiple error details of various types to provide comprehensive error information to clients.
The main benefits of using ugrpc::RichStatus include:
- Structured error information that can be programmatically processed by clients
- Support for multiple error detail types in a single response
- Easy conversion to and from standard gRPC status objects
- Compliance with Google AIP-193 standard for error details
Creating RichStatus with Error Details
You can create a ugrpc::RichStatus in several ways:
Default constructor creates an OK status with no error details:
From a gRPC status:
grpc::Status grpc_status{grpc::StatusCode::NOT_FOUND, "Resource not found"};
With status code, message, and error details:
grpc::StatusCode::INVALID_ARGUMENT,
"Invalid request",
};
Adding details after creation:
Supported Error Detail Types
ugrpc::RichStatus supports all standard Google error detail types:
Extracting Error Details on the Client Side
When a client receives an error response with ugrpc::RichStatus details, it can extract specific error details using the TryGetDetail method:
UTEST_F(GrpcClientWithDetailedRichErrorTest, TryGetErrorDetail) {
sample::ugrpc::GreetingRequest out;
out.set_name("userver");
try {
GetClient().SayHello(out);
FAIL() << "Expected ResourceExhaustedError";
const auto& status = e.GetStatus();
EXPECT_TRUE(gstatus.has_value());
EXPECT_TRUE(help_detail.has_value());
EXPECT_EQ(help_detail->links.size(), 1);
EXPECT_EQ(help_detail->links[0].description, "test_url");
EXPECT_EQ(help_detail->links[0].url, "http://help.url/auth/fts-documentation/tvm");
EXPECT_TRUE(quota_failure_detail.has_value());
EXPECT_EQ(quota_failure_detail->violations.size(), 1);
EXPECT_EQ(quota_failure_detail->violations[0].subject, "123-pipepline000");
EXPECT_EQ(quota_failure_detail->violations[0].description, "fts quota [fts-receive] exhausted");
}
}
Integration with gRPC Services
In a gRPC service implementation, you can return a ugrpc::RichStatus by converting it to a gRPC status:
SayHelloResult SayHello(CallContext& , sample::ugrpc::GreetingRequest&& ) override {
ugrpc::RichStatus rich_status{
grpc::StatusCode::RESOURCE_EXHAUSTED,
"message",
ugrpc::Help{{{"test_url", "http://help.url/auth/fts-documentation/tvm"}}},
ugrpc::QuotaFailure{{{"123-pipepline000", "fts quota [fts-receive] exhausted"}}},
};
return rich_status.ToGrpcStatus();
}
The ugrpc::RichStatus is automatically converted to a gRPC status with serialized error details that can be unpacked by the client.
Examples
ErrorInfo Example
grpc::StatusCode::UNAUTHENTICATED,
"Authentication failed",
"INVALID_TOKEN",
"auth.example.com",
{{"token_type", "bearer"}, {"error", "expired"}},
},
};
RetryInfo Example
grpc::StatusCode::UNAVAILABLE,
"Service overloaded",
};
BadRequest Example
grpc::StatusCode::INVALID_ARGUMENT,
"Invalid request",
{"user.email", "Invalid email format"},
{"user.age", "Must be between 18 and 120"},
{"user.name", "Required field is missing"},
}},
};
LocalizedMessage Example
grpc::StatusCode::INVALID_ARGUMENT,
"Invalid email address",
"ru-RU",
"Неверный формат электронной почты. Пожалуйста, используйте name@example.com",
},
};
For more information about the Google error model, see: