Documentation ¶
Overview ¶
Package status is a drop-in replacement for the google.golang.org/grpc/status package, but is compatible with merry errors.
Errors created by this package are merry errors, and can be augmented with additional information, like any other merry error.
Functions which translate errors into a Status, or into a Code are compatible with the new error wrapping conventions, using errors.Is and errors.As to extract a Status from nested errors.
This package also adds additional utilities for adding Codes to an existing error, and converting a merry error into a Status.
Index ¶
- Variables
- func AttachStatus(err error, status *Status) error
- func Code(err error) codes.Code
- func CodeFromHTTPStatus(httpStatus int) codes.Code
- func DetailsFromError(err error) []proto.Message
- func Error(c codes.Code, msg string) error
- func ErrorProto(s *spb.Status) error
- func Errorf(c codes.Code, format string, a ...interface{}) error
- func WithCode(code codes.Code) merry.Wrapper
- type GRPCStatuser
- type Status
Constants ¶
This section is empty.
Variables ¶
var DefaultLocalizedMessageLocale = "en-US"
DefaultLocalizedMessageLocale is the value used when encoding a merry.UserMessage() to a errdetails.LocalizedMessage.
Functions ¶
func AttachStatus ¶ added in v2.1.0
AttachStatus associates a Status with an error. status.FromError and status.Convert will return this value instead of deriving a status from the error.
This should be used by GRPC handlers which want to craft a specific status.Status to return. The result of this function should be returned by the handler *without any further error wrapping* (because grpc does not support error wrapping), like this:
func MyHandler(ctx context.Context, req *MyReq) (*MyResp, error) { resp, err := handle(ctx, req) if err != nil { sts := status.Convert(err) // customize the status return nil, status.AttachStatus(err, sts) } }
tl;dr ¶
This would typically be done like this:
func MyHandler(ctx context.Context, req *MyReq) (*MyResp, error) { resp, err := handle(ctx, req) if err != nil { sts := status.Convert(err) // customize the status return nil, status.Err() } }
The trouble with that is that the original error is lost. If you have interceptors which log errors, they will never see the original error, which might have had all sorts of interesting information in them. You also can't do this:
return merry.Wrap(sts.Err(), merry.WithCause(err))
...because the grpc package doesn't handle wrapped errors. You cannot wrap sts.Err() any further, or the status will be lost. According to this PR, it seems this is intentional, and wrapped errors may never be supported.
This is intentionally *not* a merry wrapper function, because the result of this function should never be wrapped any further. It needs to be returned as-is from the handler in order for the grpc code to find your status.Status and return it to the client.
func Code ¶
Code returns the grpc response code for an error. It is similar to status.Code(), and should behave identically to that function for non-merry errors. If err is a merry error, this supports mapping some merry constructs to grpc codes. The rules like a switch statement:
- err is nil: codes.OK - code previously set with WithCode() - errors.As(GRPCStatuser): return code from Status - errors.Is(context.DeadlineExceeded): codes.DeadlineExceeded - errors.Is(context.Canceled: codes.Canceled - default: CodeFromHTTPStatus(), which defaults to codes.Unknown
func CodeFromHTTPStatus ¶
CodeFromHTTPStatus returns a grpc code from an http status code. It returns the inverse of github.com/grpc-ecosystem/grpc-gateway/v2/runtime.HTTPStatusFromCode, plus some additional HTTP code mappings.
If there is no mapping for the status code, it defaults to OK for status codes between 200 and 299, and Unknown for all others.
func DetailsFromError ¶
DetailsFromError derives status details from context attached to the error:
- if the err has a user message, it will be converted into a LocalizedMessage. - if the err has a stack, it will be converted into a DebugInfo.
Returns nil if no details are derived from the error.
func ErrorProto ¶
ErrorProto returns an error representing s. If s.Code is OK, returns nil.
Types ¶
type GRPCStatuser ¶
type GRPCStatuser interface {
GRPCStatus() *Status
}
GRPCStatuser knows how to return a Status.
type Status ¶
Status references google.golang.org/grpc/status
func Convert ¶
Convert is a convenience function which removes the need to handle the boolean return value from FromError.
func FromContextError ¶
FromContextError remains for compatibility with the status package, but it does the same thing as Convert/FromError. The logic for translating context errors into appropriate grpc codes is built in to FromError now.
func FromError ¶
FromError returns a Status representing err if the error or any of its causes can be coerced to a GRPCStatuser with errors.As(). Errors created by this package or by google.golang.org/grpc/status have a Status that will be found by this function. A Status can also be associated with an existing error using WithStatus.
If a Status is found, the ok return value will be true.
If no Status is found, ok is false, and a new Status is constructed from the error.