code error

This commit is contained in:
withchao 2023-03-16 16:32:42 +08:00
parent 38d3c5d94d
commit 1f935531f6
7 changed files with 272 additions and 15 deletions

View File

@ -19,12 +19,8 @@ func apiSuccess(data any) *apiResponse {
func apiError(err error) *apiResponse {
unwrap := errs.Unwrap(err)
var dlt string
if unwrap != err {
dlt = err.Error()
}
if codeErr, ok := unwrap.(errs.CodeError); ok {
return &apiResponse{ErrCode: codeErr.Code(), ErrMsg: codeErr.Msg(), ErrDlt: dlt}
return &apiResponse{ErrCode: codeErr.Code(), ErrMsg: codeErr.Msg(), ErrDlt: codeErr.Detail()}
}
return &apiResponse{ErrCode: errs.ServerInternalError, ErrMsg: err.Error(), ErrDlt: dlt}
return &apiResponse{ErrCode: errs.ServerInternalError, ErrMsg: err.Error()}
}

View File

@ -6,10 +6,11 @@ import (
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/constant"
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/log"
"github.com/OpenIMSDK/Open-IM-Server/pkg/errs"
"github.com/OpenIMSDK/Open-IM-Server/pkg/proto/errinfo"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/wrapperspb"
"strings"
)
func GrpcClient() grpc.DialOption {
@ -46,8 +47,10 @@ func rpcClientInterceptor(ctx context.Context, method string, req, resp interfac
return errs.NewCodeError(errs.ServerInternalError, err.Error()).Wrap()
}
if details := sta.Details(); len(details) > 0 {
if v, ok := details[0].(*wrapperspb.StringValue); ok {
return errs.NewCodeError(int(sta.Code()), sta.Message()).Wrap(v.String())
errInfo, ok := details[0].(*errinfo.ErrorInfo)
if ok {
s := strings.Join(errInfo.Warp, "->") + errInfo.Cause
return errs.NewCodeError(int(sta.Code()), sta.Message()).WithDetail(s).Wrap()
}
}
return errs.NewCodeError(int(sta.Code()), sta.Message()).Wrap()

View File

@ -6,13 +6,16 @@ import (
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/log"
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/mw/specialerror"
"github.com/OpenIMSDK/Open-IM-Server/pkg/errs"
"github.com/OpenIMSDK/Open-IM-Server/pkg/proto/wrapperspb"
"github.com/OpenIMSDK/Open-IM-Server/pkg/proto/errinfo"
"github.com/pkg/errors"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"math"
"runtime"
"runtime/debug"
"strings"
)
const OperationID = "operationID"
@ -31,7 +34,22 @@ func rpcServerInterceptor(ctx context.Context, req interface{}, info *grpc.Unary
if r := recover(); r != nil {
log.ZError(ctx, "rpc panic", nil, "FullMethod", info.FullMethod, "type:", fmt.Sprintf("%T", r), "panic:", r)
fmt.Println("stack info:", string(debug.Stack()))
err = errs.ErrInternalServer
pc, file, line, ok := runtime.Caller(4)
if ok {
panic("get runtime.Caller failed")
}
errInfo := &errinfo.ErrorInfo{
Path: file,
Line: uint32(line),
Name: runtime.FuncForPC(pc).Name(),
Cause: fmt.Sprintf("%s", r),
Warp: nil,
}
sta, err := status.New(codes.Code(errs.ErrInternalServer.Code()), errs.ErrInternalServer.Msg()).WithDetails(errInfo)
if err != nil {
panic(err)
}
err = sta.Err()
}
}()
funcName := info.FullMethod
@ -68,14 +86,37 @@ func rpcServerInterceptor(ctx context.Context, req interface{}, info *grpc.Unary
code = errs.ServerInternalError
}
grpcStatus := status.New(codes.Code(code), codeErr.Msg())
var errInfo *errinfo.ErrorInfo
if unwrap != err {
stack := fmt.Sprintf("%+v", err)
if details, err := grpcStatus.WithDetails(wrapperspb.String(stack)); err == nil {
grpcStatus = details
sti, ok := err.(interface{ StackTrace() errors.StackTrace })
if ok {
log.ZWarn(ctx, "rpc server resp", err, "funcName", funcName, "unwrap", unwrap.Error(), "stack", fmt.Sprintf("%+v", err))
if fs := sti.StackTrace(); len(fs) > 0 {
pc := uintptr(fs[0])
fn := runtime.FuncForPC(pc)
file, line := fn.FileLine(pc)
errInfo = &errinfo.ErrorInfo{
Path: file,
Line: uint32(line),
Name: fn.Name(),
Cause: unwrap.Error(),
Warp: nil,
}
if arr := strings.Split(err.Error(), ": "); len(arr) > 1 {
errInfo.Warp = arr[:len(arr)-1]
}
}
}
}
if errInfo == nil {
errInfo = &errinfo.ErrorInfo{Cause: err.Error()}
}
details, err := grpcStatus.WithDetails(errInfo)
if err != nil {
panic(err)
}
log.ZError(ctx, "rpc server resp", err, "funcName", funcName)
return nil, grpcStatus.Err()
return nil, details.Err()
}
func GrpcServer() grpc.ServerOption {

View File

@ -9,6 +9,8 @@ import (
type CodeError interface {
Code() int
Msg() string
Detail() string
WithDetail(detail string) CodeError
Is(err error) bool
Wrap(msg ...string) error
error
@ -35,6 +37,24 @@ func (e *codeError) Msg() string {
return e.msg
}
func (e *codeError) Detail() string {
return e.detail
}
func (e *codeError) WithDetail(detail string) CodeError {
var d string
if e.detail == "" {
d = detail
} else {
d = e.detail + ", " + detail
}
return &codeError{
code: e.code,
msg: e.msg,
detail: d,
}
}
func (e *codeError) Wrap(w ...string) error {
return errors.Wrap(e, strings.Join(w, ", "))
}

View File

@ -0,0 +1,183 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.29.1
// protoc v4.22.0
// source: errinfo/errinfo.proto
package errinfo
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type ErrorInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path"`
Line uint32 `protobuf:"varint,2,opt,name=line,proto3" json:"line"`
Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name"`
Cause string `protobuf:"bytes,4,opt,name=cause,proto3" json:"cause"`
Warp []string `protobuf:"bytes,5,rep,name=warp,proto3" json:"warp"`
}
func (x *ErrorInfo) Reset() {
*x = ErrorInfo{}
if protoimpl.UnsafeEnabled {
mi := &file_errinfo_errinfo_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ErrorInfo) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ErrorInfo) ProtoMessage() {}
func (x *ErrorInfo) ProtoReflect() protoreflect.Message {
mi := &file_errinfo_errinfo_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ErrorInfo.ProtoReflect.Descriptor instead.
func (*ErrorInfo) Descriptor() ([]byte, []int) {
return file_errinfo_errinfo_proto_rawDescGZIP(), []int{0}
}
func (x *ErrorInfo) GetPath() string {
if x != nil {
return x.Path
}
return ""
}
func (x *ErrorInfo) GetLine() uint32 {
if x != nil {
return x.Line
}
return 0
}
func (x *ErrorInfo) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *ErrorInfo) GetCause() string {
if x != nil {
return x.Cause
}
return ""
}
func (x *ErrorInfo) GetWarp() []string {
if x != nil {
return x.Warp
}
return nil
}
var File_errinfo_errinfo_proto protoreflect.FileDescriptor
var file_errinfo_errinfo_proto_rawDesc = []byte{
0x0a, 0x15, 0x65, 0x72, 0x72, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x65, 0x72, 0x72, 0x69, 0x6e, 0x66,
0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53,
0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x71,
0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x70,
0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12,
0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x6c,
0x69, 0x6e, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x61, 0x75, 0x73, 0x65,
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x61, 0x75, 0x73, 0x65, 0x12, 0x12, 0x0a,
0x04, 0x77, 0x61, 0x72, 0x70, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x77, 0x61, 0x72,
0x70, 0x42, 0x37, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x44, 0x4b, 0x2f, 0x4f, 0x70, 0x65, 0x6e, 0x2d, 0x49,
0x4d, 0x2d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x2f, 0x65, 0x72, 0x72, 0x69, 0x6e, 0x66, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
}
var (
file_errinfo_errinfo_proto_rawDescOnce sync.Once
file_errinfo_errinfo_proto_rawDescData = file_errinfo_errinfo_proto_rawDesc
)
func file_errinfo_errinfo_proto_rawDescGZIP() []byte {
file_errinfo_errinfo_proto_rawDescOnce.Do(func() {
file_errinfo_errinfo_proto_rawDescData = protoimpl.X.CompressGZIP(file_errinfo_errinfo_proto_rawDescData)
})
return file_errinfo_errinfo_proto_rawDescData
}
var file_errinfo_errinfo_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_errinfo_errinfo_proto_goTypes = []interface{}{
(*ErrorInfo)(nil), // 0: OpenIMServer.protobuf.ErrorInfo
}
var file_errinfo_errinfo_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_errinfo_errinfo_proto_init() }
func file_errinfo_errinfo_proto_init() {
if File_errinfo_errinfo_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_errinfo_errinfo_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ErrorInfo); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_errinfo_errinfo_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_errinfo_errinfo_proto_goTypes,
DependencyIndexes: file_errinfo_errinfo_proto_depIdxs,
MessageInfos: file_errinfo_errinfo_proto_msgTypes,
}.Build()
File_errinfo_errinfo_proto = out.File
file_errinfo_errinfo_proto_rawDesc = nil
file_errinfo_errinfo_proto_goTypes = nil
file_errinfo_errinfo_proto_depIdxs = nil
}

View File

@ -0,0 +1,13 @@
syntax = "proto3";
package OpenIMServer.protobuf;
option go_package = "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/errinfo";
message ErrorInfo {
string path = 1;
uint32 line = 2;
string name = 3;
string cause = 4;
repeated string warp = 5;
}

View File

@ -1,5 +1,6 @@
protoc --go_out=plugins=grpc:./auth --go_opt=module=github.com/OpenIMSDK/Open-IM-Server/pkg/proto/auth auth/auth.proto
protoc --go_out=plugins=grpc:./conversation --go_opt=module=github.com/OpenIMSDK/Open-IM-Server/pkg/proto/conversation conversation/conversation.proto
protoc --go_out=plugins=grpc:./errinfo --go_opt=module=github.com/OpenIMSDK/Open-IM-Server/pkg/proto/errinfo errinfo/errinfo.proto
protoc --go_out=plugins=grpc:./friend --go_opt=module=github.com/OpenIMSDK/Open-IM-Server/pkg/proto/friend friend/friend.proto
protoc --go_out=plugins=grpc:./group --go_opt=module=github.com/OpenIMSDK/Open-IM-Server/pkg/proto/group group/group.proto
protoc --go_out=plugins=grpc:./msg --go_opt=module=github.com/OpenIMSDK/Open-IM-Server/pkg/proto/msg msg/msg.proto