github.com/nyan233/littlerpc@v0.4.6-0.20230316182519-0c8d5c48abaf/core/common/errorhandler/errorhandler.go (about) 1 package errorhandler 2 3 import ( 4 "encoding/json" 5 "fmt" 6 error2 "github.com/nyan233/littlerpc/core/protocol/error" 7 "github.com/nyan233/littlerpc/core/utils/convert" 8 "runtime" 9 "strings" 10 ) 11 12 // DefaultErrHandler 不带栈追踪的默认错误处理器 13 var DefaultErrHandler = New() 14 15 type marshalStack struct { 16 Stack stack `json:"stack"` 17 } 18 19 type stack []string 20 21 func (s stack) MarshalJSON() ([]byte, error) { 22 if s == nil { 23 return []byte("null"), nil 24 } 25 var sb strings.Builder 26 sb.WriteByte('[') 27 for i := len(s) - 1; i >= 0; i-- { 28 sb.WriteByte('"') 29 sb.WriteString(s[i]) 30 sb.WriteByte('"') 31 if i != 0 { 32 sb.WriteByte(',') 33 } 34 } 35 sb.WriteByte(']') 36 return convert.StringToBytes(sb.String()), nil 37 } 38 39 type lRPCStackTraceError struct { 40 RpcCode int `json:"code"` 41 RpcMessage string `json:"message"` 42 RpcMores []interface{} `json:"mores"` 43 RpcStack stack `json:"stack"` 44 } 45 46 func error2LRPCError(err error2.LErrorDesc) *lRPCStackTraceError { 47 return &lRPCStackTraceError{ 48 RpcCode: err.Code(), 49 RpcMessage: err.Message(), 50 RpcMores: append(err.Mores()), 51 RpcStack: make([]string, 0, 8), 52 } 53 } 54 55 func warpStackTraceError(err *lRPCStackTraceError, mores ...interface{}) *lRPCStackTraceError { 56 return &lRPCStackTraceError{ 57 RpcCode: err.RpcCode, 58 RpcMessage: err.RpcMessage, 59 RpcMores: append(err.RpcMores, mores...), 60 RpcStack: err.RpcStack, 61 } 62 } 63 64 func (l *lRPCStackTraceError) Code() int { 65 return l.RpcCode 66 } 67 68 func (l *lRPCStackTraceError) Message() string { 69 return l.RpcMessage 70 } 71 72 func (l *lRPCStackTraceError) AppendMore(more interface{}) { 73 l.RpcMores = append(l.RpcMores, more) 74 } 75 76 func (l *lRPCStackTraceError) Mores() []interface{} { 77 return l.RpcMores 78 } 79 80 func (l *lRPCStackTraceError) MarshalMores() ([]byte, error) { 81 mores := l.Mores() 82 mores = append(mores, &marshalStack{Stack: l.RpcStack}) 83 return json.Marshal(mores) 84 } 85 86 func (l *lRPCStackTraceError) UnmarshalMores(bytes []byte) error { 87 return json.Unmarshal(bytes, &l.RpcMores) 88 } 89 90 func (l *lRPCStackTraceError) Error() string { 91 type PrintError struct { 92 RpcCode int `json:"code"` 93 RpcMessage string `json:"message"` 94 RpcMores []interface{} `json:"mores"` 95 } 96 mores := l.Mores() 97 mores = append(mores, &marshalStack{Stack: l.RpcStack}) 98 bytes, err := json.Marshal(&PrintError{ 99 RpcCode: l.Code(), 100 RpcMessage: l.Message(), 101 RpcMores: mores, 102 }) 103 if err != nil { 104 panic("json.Marshal failed : " + err.Error()) 105 } 106 return convert.BytesToString(bytes) 107 } 108 109 type JsonErrorHandler struct { 110 openStackTrace bool 111 } 112 113 func NewStackTrace() error2.LErrors { 114 return &JsonErrorHandler{ 115 openStackTrace: true, 116 } 117 } 118 119 func New() error2.LErrors { 120 return new(JsonErrorHandler) 121 } 122 123 func (j JsonErrorHandler) LNewErrorDesc(code int, message string, mores ...interface{}) error2.LErrorDesc { 124 if !j.openStackTrace { 125 return error2.LNewStdError(code, message, mores...) 126 } 127 err := error2LRPCError(error2.LNewStdError(code, message, mores...)) 128 // runtime.Caller即使有重复的代码也不能抽到公共函数中, skip参数对性能的影响很大 129 _, file, line, ok := runtime.Caller(1) 130 if !ok { 131 err.RpcStack = append(err.RpcStack, "???.go:???") 132 } else { 133 err.RpcStack = append(err.RpcStack, fmt.Sprintf("%s:%d", file, line)) 134 } 135 return err 136 } 137 138 func (j JsonErrorHandler) LWarpErrorDesc(desc error2.LErrorDesc, mores ...interface{}) error2.LErrorDesc { 139 if !j.openStackTrace { 140 return error2.LWarpStdError(desc, mores...) 141 } 142 err, _ := desc.(*lRPCStackTraceError) 143 if err == nil { 144 err = error2LRPCError(error2.LWarpStdError(desc, mores...)) 145 } else { 146 err = warpStackTraceError(err, mores...) 147 } 148 // runtime.Caller即使有重复的代码也不能抽到公共函数中, skip参数对性能的影响很大 149 _, file, line, ok := runtime.Caller(1) 150 if !ok { 151 err.RpcStack = append(err.RpcStack, "???.go:???") 152 } else { 153 err.RpcStack = append(err.RpcStack, fmt.Sprintf("%s:%d", file, line)) 154 } 155 return err 156 }