Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions kokoro/build_nuget.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,5 @@ build/expand_dev_version.sh
(cd src/Grpc.AspNetCore && dotnet pack --configuration Release --output ../../artifacts -p:ContinuousIntegrationBuild=true)
(cd src/Grpc.AspNetCore.Web && dotnet pack --configuration Release --output ../../artifacts -p:ContinuousIntegrationBuild=true)
(cd src/Grpc.AspNetCore.HealthChecks && dotnet pack --configuration Release --output ../../artifacts -p:ContinuousIntegrationBuild=true)
(cd src/Grpc.StatusProto && dotnet pack --configuration Release --output ../../artifacts -p:ContinuousIntegrationBuild=true)
(cd src/dotnet-grpc && dotnet pack --configuration Release --output ../../artifacts -p:ContinuousIntegrationBuild=true)
35 changes: 20 additions & 15 deletions src/Grpc.StatusProto/ExceptionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,40 +18,45 @@
namespace Grpc.Core;

/// <summary>
/// Extensions methods for <see cref="System.Exception"/>
/// Extensions methods for converting <see cref="Exception"/> to <see cref="DebugInfo"/>.
/// </summary>
public static class ExceptionExtensions
{
/// <summary>
/// Create a <see cref="Google.Rpc.DebugInfo"/> from an <see cref="System.Exception"/>,
/// Create a <see cref="DebugInfo"/> from an <see cref="Exception"/>,
/// populating the Message and StackTrace from the exception.
/// Note: experimental API that can change or be removed without any prior notice.
/// </summary>
/// <remarks>
/// <example>
/// For example:
/// <code>
/// try { /* ... */
/// try
/// {
/// /* ... */
/// }
/// catch (Exception e) {
/// Google.Rpc.Status status = new() {
/// Code = (int)StatusCode.Internal,
/// Message = "Internal error",
/// Details = {
/// // populate debugInfo from the exception
/// Any.Pack(e.ToRpcDebugInfo())
/// }
/// };
/// // ...
/// catch (Exception e)
/// {
/// Google.Rpc.Status status = new()
/// {
/// Code = (int)StatusCode.Internal,
/// Message = "Internal error",
/// Details =
/// {
/// // populate debugInfo from the exception
/// Any.Pack(e.ToRpcDebugInfo())
/// }
/// };
/// // ...
/// }
/// </code>
/// </example>
/// </remarks>
/// <param name="exception"></param>
/// <param name="exception">The exception to create a <see cref="DebugInfo"/> from.</param>
/// <param name="innerDepth">Maximum number of inner exceptions to include in the StackTrace. Defaults
/// to not including any inner exceptions</param>
/// <returns>
/// A new <see cref="Google.Rpc.DebugInfo"/> populated from the exception.
/// A new <see cref="DebugInfo"/> populated from the exception.
/// </returns>
public static DebugInfo ToRpcDebugInfo(this Exception exception, int innerDepth = 0)
{
Expand Down
24 changes: 11 additions & 13 deletions src/Grpc.StatusProto/MetadataExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,24 @@
namespace Grpc.Core;

/// <summary>
/// Extension methods for the Grpc.Core.Metadata
/// Extension methods for using <see cref="Google.Rpc.Status"/> with <see cref="Metadata"/>.
/// </summary>
public static class MetadataExtensions
{
/// <summary>
/// Name of key in the metadata for the binary encoding of
/// <see cref="Google.Rpc.Status"/>
/// Name of key in the metadata for the binary encoding of <see cref="Google.Rpc.Status"/>.
/// </summary>
public const string StatusDetailsTrailerName = "grpc-status-details-bin";

/// <summary>
/// Get the <see cref="Google.Rpc.Status"/> from the metadata.
/// Get <see cref="Google.Rpc.Status"/> from the metadata with the <c>grpc-status-details-bin</c> key.
/// Note: experimental API that can change or be removed without any prior notice.
/// </summary>
/// <param name="metadata"></param>
/// <param name="ignoreParseError">if true then null is returned on a parsing error,
/// otherwise <see cref="Google.Protobuf.InvalidProtocolBufferException"/>
/// will be thrown if the metadata cannot be parsed.</param>
/// <param name="metadata">The metadata.</param>
/// <param name="ignoreParseError">If true then <see langword="null"/> is returned on a parsing error,
/// otherwise an error will be thrown if the metadata cannot be parsed.</param>
/// <returns>
/// The found <see cref="Google.Rpc.Status"/> or null if it was
/// The <see cref="Google.Rpc.Status"/> or <see langword="null"/> if <c>grpc-status-details-bin</c> was
/// not present or could the data could not be parsed.
/// </returns>
public static Google.Rpc.Status? GetRpcStatus(this Metadata metadata, bool ignoreParseError = false)
Expand All @@ -61,12 +59,12 @@ public static class MetadataExtensions
}

/// <summary>
/// Add <see cref="Google.Rpc.Status"/> to the metadata.
/// Any existing status in the metadata will be overwritten.
/// Add <see cref="Google.Rpc.Status"/> to the metadata with the <c>grpc-status-details-bin</c> key.
/// An existing status in the metadata will be overwritten.
/// Note: experimental API that can change or be removed without any prior notice.
/// </summary>
/// <param name="metadata"></param>
/// <param name="status">Status to add</param>
/// <param name="metadata">The metadata.</param>
/// <param name="status">The status to add.</param>
public static void SetRpcStatus(this Metadata metadata, Google.Rpc.Status status)
{
ArgumentNullThrowHelper.ThrowIfNull(metadata);
Expand Down
4 changes: 2 additions & 2 deletions src/Grpc.StatusProto/RpcExceptionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
namespace Grpc.Core;

/// <summary>
/// Extensions to <see cref="Grpc.Core.RpcException"/> for handling rich error model.
/// Extension methods for getting <see cref="Google.Rpc.Status"/> from <see cref="RpcException"/>.
/// </summary>
public static class RpcExceptionExtensions
{
Expand All @@ -26,7 +26,7 @@ public static class RpcExceptionExtensions
/// from the trailers in an <see cref="RpcException"/>, if present.
/// Note: experimental API that can change or be removed without any prior notice.
/// </summary>
/// <param name="ex">The RPC exception to retrieve details from. Must not be null.</param>
/// <param name="ex">The <see cref="RpcException"/> to retrieve details from. Must not be null.</param>
/// <returns>The <see cref="Google.Rpc.Status"/> message specified in the exception, or null
/// if there is no such information.</returns>
public static Google.Rpc.Status? GetRpcStatus(this RpcException ex)
Expand Down
66 changes: 35 additions & 31 deletions src/Grpc.StatusProto/RpcStatusExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,38 +17,40 @@
namespace Grpc.Core;

/// <summary>
/// Extensions for <see cref="Google.Rpc.Status"/> to retrieve detailed error information.
/// Based on ideas from:
/// https://github.com/googleapis/gax-dotnet/blob/main/Google.Api.Gax.Grpc/RpcExceptionExtensions.cs
/// Extensions methods for converting <see cref="Google.Rpc.Status"/> to <see cref="RpcException"/>.
/// </summary>
public static class RpcStatusExtensions
{
/// <summary>
/// Create a <see cref="RpcException"/> from the <see cref="Google.Rpc.Status"/>
/// Create a <see cref="RpcException"/> from the <see cref="Google.Rpc.Status"/>.
/// Note: experimental API that can change or be removed without any prior notice.
/// </summary>
/// <remarks>
/// <para>
/// The <see cref="Grpc.Core.Status.StatusCode"/> and <see cref="Grpc.Core.Status.Detail"/> in the
/// <see cref="Grpc.Core.Status"/> within the exception are populated from the details in the
/// <see cref="Google.Rpc.Status"/>
/// The <see cref="Grpc.Core.Status.StatusCode"/> and <see cref="Grpc.Core.Status.Detail"/> on
/// <see cref="Grpc.Core.Status"/> within the exception are populated from the details from
/// <see cref="Google.Rpc.Status"/>.
/// </para>
/// <para>
/// <example>
/// Example:
/// <code>
/// throw new Google.Rpc.Status {
/// Code = (int) StatusCode.NotFound,
/// Message = "Simple error message",
/// Details = {
/// Any.Pack(new ErrorInfo { Domain = "example", Reason = "some reason" })
/// }
/// }.ToRpcException();
/// var status = new Google.Rpc.Status
/// {
/// Code = (int) StatusCode.NotFound,
/// Message = "Simple error message",
/// Details =
/// {
/// Any.Pack(new ErrorInfo { Domain = "example", Reason = "some reason" })
/// }
/// };
///
/// throw status.ToRpcException();
/// </code>
/// </example>
/// </para>
/// </remarks>
/// <param name="status">The RPC status. Must not be null</param>
/// <param name="status">The <see cref="Google.Rpc.Status"/>. Must not be null</param>
/// <returns>A <see cref="RpcException"/> populated with the details from the status.</returns>
public static RpcException ToRpcException(this Google.Rpc.Status status)
{
Expand All @@ -66,12 +68,12 @@ public static RpcException ToRpcException(this Google.Rpc.Status status)
//
// Check here that we can convert Google.Rpc.Status.Code to Grpc.Core.StatusCode,
// and if not use StatusCode.Unknown.
var statusCode = System.Enum.IsDefined(typeof(StatusCode), status.Code) ? (StatusCode)status.Code : StatusCode.Unknown;
var statusCode = Enum.IsDefined(typeof(StatusCode), status.Code) ? (StatusCode)status.Code : StatusCode.Unknown;
return status.ToRpcException(statusCode, status.Message);
}

/// <summary>
/// Create a <see cref="RpcException"/> from the <see cref="Google.Rpc.Status"/>
/// Create a <see cref="RpcException"/> from the <see cref="Google.Rpc.Status"/>.
/// Note: experimental API that can change or be removed without any prior notice.
/// </summary>
/// <remarks>
Expand All @@ -84,29 +86,31 @@ public static RpcException ToRpcException(this Google.Rpc.Status status)
/// <example>
/// Example:
/// <code>
/// throw new Google.Rpc.Status {
/// Code = (int) StatusCode.NotFound,
/// Message = "Simple error message",
/// Details = {
/// Any.Pack(new ErrorInfo { Domain = "example", Reason = "some reason" })
/// }
/// }.ToRpcException(StatusCode.NotFound, "status message");
/// var status = new Google.Rpc.Status
/// {
/// Code = (int) StatusCode.NotFound,
/// Message = "Simple error message",
/// Details =
/// {
/// Any.Pack(new ErrorInfo { Domain = "example", Reason = "some reason" })
/// }
/// };
///
/// throw status.ToRpcException(StatusCode.NotFound, "status message");
/// </code>
/// </example>
/// </para>
/// </remarks>
/// <param name="status"></param>
/// <param name="statusCode">The status to set in the contained <see cref="Grpc.Core.Status"/></param>
/// <param name="message">The details to set in the contained <see cref="Grpc.Core.Status"/></param>
/// <returns></returns>
/// <param name="status">The <see cref="Google.Rpc.Status"/>. Must not be null</param>
/// <param name="statusCode">The status to set in the exception's <see cref="Grpc.Core.Status"/></param>
/// <param name="message">The details to set in the exception's <see cref="Grpc.Core.Status"/></param>
/// <returns>A <see cref="RpcException"/> populated with the details from the status.</returns>
public static RpcException ToRpcException(this Google.Rpc.Status status, StatusCode statusCode, string message)
{
ArgumentNullThrowHelper.ThrowIfNull(status);

var metadata = new Metadata();
metadata.SetRpcStatus(status);
return new RpcException(
new Grpc.Core.Status(statusCode, message),
metadata);
return new RpcException(new Status(statusCode, message), metadata);
}
}