Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add error cause for statck trace #1910

Merged
merged 10 commits into from
Apr 10, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 7 additions & 2 deletions cmd/protoc-gen-go-errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
"fmt"
"strings"

"golang.org/x/text/cases"
"golang.org/x/text/language"

"github.com/go-kratos/kratos/cmd/protoc-gen-go-errors/v2/errors"
"google.golang.org/protobuf/compiler/protogen"
"google.golang.org/protobuf/proto"
Expand All @@ -14,6 +17,8 @@ const (
fmtPackage = protogen.GoImportPath("fmt")
)

var enCases = cases.Title(language.AmericanEnglish)

// generateFile generates a _errors.pb.go file containing kratos errors definitions.
func generateFile(gen *protogen.Plugin, file *protogen.File) *protogen.GeneratedFile {
if len(file.Enums) == 0 {
Expand Down Expand Up @@ -98,10 +103,10 @@ func case2Camel(name string) string {
if upperName == name {
name = strings.ToLower(name)
}
return strings.Title(name)
return enCases.String(name)
}
name = strings.ToLower(name)
name = strings.Replace(name, "_", " ", -1)
name = strings.Title(name)
name = enCases.String(name)
return strings.Replace(name, " ", "", -1)
}
5 changes: 4 additions & 1 deletion cmd/protoc-gen-go-errors/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ module github.com/go-kratos/kratos/cmd/protoc-gen-go-errors/v2

go 1.16

require google.golang.org/protobuf v1.27.1
require (
golang.org/x/text v0.3.7 // indirect
google.golang.org/protobuf v1.27.1
)
3 changes: 3 additions & 0 deletions cmd/protoc-gen-go-errors/go.sum
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
Expand Down
3 changes: 1 addition & 2 deletions cmd/protoc-gen-go-http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

"google.golang.org/protobuf/reflect/protoreflect"

"github.com/go-kratos/kratos/v2"
"google.golang.org/genproto/googleapis/api/annotations"
"google.golang.org/protobuf/compiler/protogen"
"google.golang.org/protobuf/proto"
Expand All @@ -32,7 +31,7 @@ func generateFile(gen *protogen.Plugin, file *protogen.File, omitempty bool) *pr
g := gen.NewGeneratedFile(filename, file.GoImportPath)
g.P("// Code generated by protoc-gen-go-http. DO NOT EDIT.")
g.P("// versions:")
g.P(fmt.Sprintf("// protoc-gen-go-http %s", kratos.Release))
g.P(fmt.Sprintf("// protoc-gen-go-http %s", release))
g.P()
g.P("package ", file.GoPackageName)
g.P()
Expand Down
66 changes: 50 additions & 16 deletions errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import (
httpstatus "github.com/go-kratos/kratos/v2/transport/http/status"
"google.golang.org/genproto/googleapis/rpc/errdetails"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
)

//go:generate protoc -I. --go_out=paths=source_relative:. errors.proto

const (
// UnknownCode is unknown code for error info.
UnknownCode = 500
Expand All @@ -19,21 +20,18 @@ const (
SupportPackageIsVersion1 = true
)

//go:generate protoc -I. --go_out=paths=source_relative:. errors.proto
// Error is a status error.
type Error struct {
Status
cause error
}

func (e *Error) Error() string {
return fmt.Sprintf("error: code = %d reason = %s message = %s metadata = %v", e.Code, e.Reason, e.Message, e.Metadata)
return fmt.Sprintf("error: code = %d reason = %s message = %s metadata = %v cause = %v", e.Code, e.Reason, e.Message, e.Metadata, e.cause)
}

// GRPCStatus returns the Status represented by se.
func (e *Error) GRPCStatus() *status.Status {
s, _ := status.New(httpstatus.ToGRPCCode(int(e.Code)), e.Message).
WithDetails(&errdetails.ErrorInfo{
Reason: e.Reason,
Metadata: e.Metadata,
})
return s
}
// Unwrap provides compatibility for Go 1.13 error chains.
func (e *Error) Unwrap() error { return e.cause }

// Is matches each error in the chain with the target value.
func (e *Error) Is(err error) bool {
Expand All @@ -43,19 +41,38 @@ func (e *Error) Is(err error) bool {
return false
}

// WithCause with the underlying cause of the error.
func (e *Error) WithCause(cause error) *Error {
err := Clone(e)
err.cause = cause
return err
}

// WithMetadata with an MD formed by the mapping of key, value.
func (e *Error) WithMetadata(md map[string]string) *Error {
err := proto.Clone(e).(*Error)
err := Clone(e)
err.Metadata = md
return err
}

// GRPCStatus returns the Status represented by se.
func (e *Error) GRPCStatus() *status.Status {
s, _ := status.New(httpstatus.ToGRPCCode(int(e.Code)), e.Message).
WithDetails(&errdetails.ErrorInfo{
Reason: e.Reason,
Metadata: e.Metadata,
})
return s
}

// New returns an error object for the code, message.
func New(code int, reason, message string) *Error {
return &Error{
Code: int32(code),
Message: message,
Reason: reason,
Status: Status{
Code: int32(code),
Message: message,
Reason: reason,
},
}
}

Expand Down Expand Up @@ -87,6 +104,23 @@ func Reason(err error) string {
return FromError(err).Reason
}

// Clone deep clone error to a new error.
func Clone(err *Error) *Error {
metadata := make(map[string]string, len(err.Metadata))
for k, v := range err.Metadata {
metadata[k] = v
}
return &Error{
cause: err.cause,
Status: Status{
Code: err.Code,
Reason: err.Reason,
Message: err.Message,
Metadata: metadata,
},
}
}

// FromError try to convert an error to *Error.
// It supports wrapped errors.
func FromError(err error) *Error {
Expand Down