trpc.group/trpc-go/trpc-go@v1.0.3/errs/errs.go (about) 1 // 2 // 3 // Tencent is pleased to support the open source community by making tRPC available. 4 // 5 // Copyright (C) 2023 THL A29 Limited, a Tencent company. 6 // All rights reserved. 7 // 8 // If you have downloaded a copy of the tRPC source code from Tencent, 9 // please note that tRPC source code is licensed under the Apache 2.0 License, 10 // A copy of the Apache 2.0 License is included in this file. 11 // 12 // 13 14 // Package errs provides trpc error code type, which contains errcode errmsg. 15 // These definitions are multi-language universal. 16 package errs 17 18 import ( 19 "errors" 20 "fmt" 21 "io" 22 23 trpcpb "trpc.group/trpc/trpc-protocol/pb/go/trpc" 24 ) 25 26 // trpc return code. 27 const ( 28 // RetOK means success. 29 RetOK = trpcpb.TrpcRetCode_TRPC_INVOKE_SUCCESS 30 31 // RetServerDecodeFail is the error code of the server decoding error. 32 RetServerDecodeFail = trpcpb.TrpcRetCode_TRPC_SERVER_DECODE_ERR 33 // RetServerEncodeFail is the error code of the server encoding error. 34 RetServerEncodeFail = trpcpb.TrpcRetCode_TRPC_SERVER_ENCODE_ERR 35 // RetServerNoService is the error code that the server does not call the corresponding service implementation. 36 RetServerNoService = trpcpb.TrpcRetCode_TRPC_SERVER_NOSERVICE_ERR 37 // RetServerNoFunc is the error code that the server does not call the corresponding interface implementation. 38 RetServerNoFunc = trpcpb.TrpcRetCode_TRPC_SERVER_NOFUNC_ERR 39 // RetServerTimeout is the error code that the request timed out in the server queue. 40 RetServerTimeout = trpcpb.TrpcRetCode_TRPC_SERVER_TIMEOUT_ERR 41 // RetServerOverload is the error code that the request is overloaded on the server side. 42 RetServerOverload = trpcpb.TrpcRetCode_TRPC_SERVER_OVERLOAD_ERR 43 // RetServerThrottled is the error code of the server's current limit. 44 RetServerThrottled = trpcpb.TrpcRetCode_TRPC_SERVER_LIMITED_ERR 45 // RetServerFullLinkTimeout is the server full link timeout error code. 46 RetServerFullLinkTimeout = trpcpb.TrpcRetCode_TRPC_SERVER_FULL_LINK_TIMEOUT_ERR 47 // RetServerSystemErr is the error code of the server system error. 48 RetServerSystemErr = trpcpb.TrpcRetCode_TRPC_SERVER_SYSTEM_ERR 49 // RetServerAuthFail is the error code for authentication failure. 50 RetServerAuthFail = trpcpb.TrpcRetCode_TRPC_SERVER_AUTH_ERR 51 // RetServerValidateFail is the error code for the failure of automatic validation of request parameters. 52 RetServerValidateFail = trpcpb.TrpcRetCode_TRPC_SERVER_VALIDATE_ERR 53 54 // RetClientTimeout is the error code that the request timed out on the client side. 55 RetClientTimeout = trpcpb.TrpcRetCode_TRPC_CLIENT_INVOKE_TIMEOUT_ERR 56 // RetClientFullLinkTimeout is the client full link timeout error code. 57 RetClientFullLinkTimeout = trpcpb.TrpcRetCode_TRPC_CLIENT_FULL_LINK_TIMEOUT_ERR 58 // RetClientConnectFail is the error code of the client connection error. 59 RetClientConnectFail = trpcpb.TrpcRetCode_TRPC_CLIENT_CONNECT_ERR 60 // RetClientEncodeFail is the error code of the client encoding error. 61 RetClientEncodeFail = trpcpb.TrpcRetCode_TRPC_CLIENT_ENCODE_ERR 62 // RetClientDecodeFail is the error code of the client decoding error. 63 RetClientDecodeFail = trpcpb.TrpcRetCode_TRPC_CLIENT_DECODE_ERR 64 // RetClientThrottled is the error code of the client's current limit. 65 RetClientThrottled = trpcpb.TrpcRetCode_TRPC_CLIENT_LIMITED_ERR 66 // RetClientOverload is the error code for client overload. 67 RetClientOverload = trpcpb.TrpcRetCode_TRPC_CLIENT_OVERLOAD_ERR 68 // RetClientRouteErr is the error code for the wrong ip route selected by the client. 69 RetClientRouteErr = trpcpb.TrpcRetCode_TRPC_CLIENT_ROUTER_ERR 70 // RetClientNetErr is the error code of the client network error. 71 RetClientNetErr = trpcpb.TrpcRetCode_TRPC_CLIENT_NETWORK_ERR 72 // RetClientValidateFail is the error code for the failure of automatic validation of response parameters. 73 RetClientValidateFail = trpcpb.TrpcRetCode_TRPC_CLIENT_VALIDATE_ERR 74 // RetClientCanceled is the error code for the upstream caller to cancel the request in advance. 75 RetClientCanceled = trpcpb.TrpcRetCode_TRPC_CLIENT_CANCELED_ERR 76 // RetClientReadFrameErr is the error code of the client read frame error. 77 RetClientReadFrameErr = trpcpb.TrpcRetCode_TRPC_CLIENT_READ_FRAME_ERR 78 // RetClientStreamQueueFull is the error code of the client stream queue full. 79 RetClientStreamQueueFull = trpcpb.TrpcRetCode_TRPC_STREAM_SERVER_NETWORK_ERR 80 // RetClientStreamReadEnd is the error code of the client stream end error while receiving data. 81 RetClientStreamReadEnd = trpcpb.TrpcRetCode_TRPC_STREAM_CLIENT_READ_END 82 83 // RetUnknown is the error code for unspecified errors. 84 RetUnknown = trpcpb.TrpcRetCode_TRPC_INVOKE_UNKNOWN_ERR 85 ) 86 87 // Err frame error value. 88 var ( 89 // ErrOK means success. 90 ErrOK error 91 92 // ErrServerNoService is an error that the server does not call the corresponding service implementation. 93 ErrServerNoService = NewFrameError(RetServerNoService, "server router no service") 94 // ErrServerNoFunc is an error that the server does not call the corresponding interface implementation. 95 ErrServerNoFunc = NewFrameError(RetServerNoFunc, "server router no rpc method") 96 // ErrServerTimeout is the error that the request timed out in the server queue. 97 ErrServerTimeout = NewFrameError(RetServerTimeout, "server message handle timeout") 98 // ErrServerOverload is an error that the request is overloaded on the server side. 99 ErrServerOverload = NewFrameError(RetServerOverload, "server overload") 100 // ErrServerRoutinePoolBusy is an error that the request is overloaded on the server side. 101 ErrServerRoutinePoolBusy = NewFrameError(RetServerOverload, "server goroutine pool too small") 102 // ErrServerClose is a server system error. 103 ErrServerClose = NewFrameError(RetServerSystemErr, "server close") 104 105 // ErrServerNoResponse is a server-side unresponsive error. 106 ErrServerNoResponse = NewFrameError(RetOK, "server no response") 107 // ErrClientNoResponse is the error of the client not responding. 108 ErrClientNoResponse = NewFrameError(RetOK, "client no response") 109 110 // ErrUnknown is an unknown error. 111 ErrUnknown = NewFrameError(RetUnknown, "unknown error") 112 ) 113 114 // ErrorType is the error code type, including framework error code and business error code. 115 const ( 116 ErrorTypeFramework = 1 117 ErrorTypeBusiness = 2 118 ErrorTypeCalleeFramework = 3 // The error code returned by the client call 119 // represents the downstream framework error code. 120 ) 121 122 func typeDesc(t int) string { 123 switch t { 124 case ErrorTypeFramework: 125 return "framework" 126 case ErrorTypeCalleeFramework: 127 return "callee framework" 128 default: 129 return "business" 130 } 131 } 132 133 const ( 134 // Success is the success prompt string. 135 Success = "success" 136 ) 137 138 // Error is the error code structure which contains error code type and error message. 139 type Error struct { 140 Type int 141 Code trpcpb.TrpcRetCode 142 Msg string 143 Desc string 144 145 cause error // internal error, form the error chain. 146 stack stackTrace // call stack, if the error chain already has a stack, it will not be set. 147 } 148 149 // Error implements the error interface and returns the error description. 150 func (e *Error) Error() string { 151 if e == nil { 152 return Success 153 } 154 155 if e.cause != nil { 156 return fmt.Sprintf("type:%s, code:%d, msg:%s, caused by %s", 157 typeDesc(e.Type), e.Code, e.Msg, e.cause.Error()) 158 } 159 return fmt.Sprintf("type:%s, code:%d, msg:%s", typeDesc(e.Type), e.Code, e.Msg) 160 } 161 162 // Format implements the fmt.Formatter interface. 163 func (e *Error) Format(s fmt.State, verb rune) { 164 var stackTrace stackTrace 165 defer func() { 166 if stackTrace != nil { 167 stackTrace.Format(s, verb) 168 } 169 }() 170 switch verb { 171 case 'v': 172 if s.Flag('+') { 173 _, _ = fmt.Fprintf(s, "type:%s, code:%d, msg:%s", typeDesc(e.Type), e.Code, e.Msg) 174 if e.stack != nil { 175 stackTrace = e.stack 176 } 177 if e.Unwrap() != nil { 178 _, _ = fmt.Fprintf(s, "\nCause by %+v", e.Unwrap()) 179 } 180 return 181 } 182 fallthrough 183 case 's': 184 _, _ = io.WriteString(s, e.Error()) 185 case 'q': 186 _, _ = fmt.Fprintf(s, "%q", e.Error()) 187 default: 188 _, _ = fmt.Fprintf(s, "%%!%c(errs.Error=%s)", verb, e.Error()) 189 } 190 } 191 192 // Unwrap support Go 1.13+ error chains. 193 func (e *Error) Unwrap() error { return e.cause } 194 195 // IsTimeout checks whether this error is a timeout error with error type typ. 196 func (e *Error) IsTimeout(typ int) bool { 197 return e.Type == typ && 198 (e.Code == RetClientTimeout || 199 e.Code == RetClientFullLinkTimeout || 200 e.Code == RetServerTimeout || 201 e.Code == RetServerFullLinkTimeout) 202 } 203 204 // ErrCode permits any integer defined in https://go.dev/ref/spec#Numeric_types 205 type ErrCode interface { 206 ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~int | ~uintptr 207 } 208 209 // New creates an error, which defaults to the business error type to improve business development efficiency. 210 func New[T ErrCode](code T, msg string) error { 211 err := &Error{ 212 Type: ErrorTypeBusiness, 213 Code: trpcpb.TrpcRetCode(code), 214 Msg: msg, 215 } 216 if traceable { 217 err.stack = callers() 218 } 219 return err 220 } 221 222 // Newf creates an error, the default is the business error type, msg supports format strings. 223 func Newf[T ErrCode](code T, format string, params ...interface{}) error { 224 msg := fmt.Sprintf(format, params...) 225 err := &Error{ 226 Type: ErrorTypeBusiness, 227 Code: trpcpb.TrpcRetCode(code), 228 Msg: msg, 229 } 230 if traceable { 231 err.stack = callers() 232 } 233 return err 234 } 235 236 // Wrap creates a new error contains input error. 237 // only add stack when traceable is true and the input type is not Error, this will ensure that there is no multiple 238 // stacks in the error chain. 239 func Wrap[T ErrCode](err error, code T, msg string) error { 240 if err == nil { 241 return nil 242 } 243 wrapErr := &Error{ 244 Type: ErrorTypeBusiness, 245 Code: trpcpb.TrpcRetCode(code), 246 Msg: msg, 247 cause: err, 248 } 249 var e *Error 250 // the error chain does not contain item which type is Error, add stack. 251 if traceable && !errors.As(err, &e) { 252 wrapErr.stack = callers() 253 } 254 return wrapErr 255 } 256 257 // Wrapf the same as Wrap, msg supports format strings. 258 func Wrapf[T ErrCode](err error, code T, format string, params ...interface{}) error { 259 if err == nil { 260 return nil 261 } 262 msg := fmt.Sprintf(format, params...) 263 wrapErr := &Error{ 264 Type: ErrorTypeBusiness, 265 Code: trpcpb.TrpcRetCode(code), 266 Msg: msg, 267 cause: err, 268 } 269 var e *Error 270 // the error chain does not contain item which type is Error, add stack. 271 if traceable && !errors.As(err, &e) { 272 wrapErr.stack = callers() 273 } 274 return wrapErr 275 } 276 277 // NewFrameError creates a frame error. 278 func NewFrameError[T ErrCode](code T, msg string) error { 279 err := &Error{ 280 Type: ErrorTypeFramework, 281 Code: trpcpb.TrpcRetCode(code), 282 Msg: msg, 283 Desc: "trpc", 284 } 285 if traceable { 286 err.stack = callers() 287 } 288 return err 289 } 290 291 // WrapFrameError the same as Wrap, except type is ErrorTypeFramework 292 func WrapFrameError[T ErrCode](err error, code T, msg string) error { 293 if err == nil { 294 return nil 295 } 296 wrapErr := &Error{ 297 Type: ErrorTypeFramework, 298 Code: trpcpb.TrpcRetCode(code), 299 Msg: msg, 300 Desc: "trpc", 301 cause: err, 302 } 303 var e *Error 304 // the error chain does not contain item which type is Error, add stack. 305 if traceable && !errors.As(err, &e) { 306 wrapErr.stack = callers() 307 } 308 return wrapErr 309 } 310 311 // Code gets the error code through error. 312 func Code(e error) trpcpb.TrpcRetCode { 313 if e == nil { 314 return RetOK 315 } 316 317 // Doing type assertion first has a slight performance boost over just using errors.As 318 // because of avoiding reflect when the assertion is probably true. 319 err, ok := e.(*Error) 320 if !ok && !errors.As(e, &err) { 321 return RetUnknown 322 } 323 if err == nil { 324 return RetOK 325 } 326 return err.Code 327 } 328 329 // Msg gets error msg through error. 330 func Msg(e error) string { 331 if e == nil { 332 return Success 333 } 334 err, ok := e.(*Error) 335 if !ok && !errors.As(e, &err) { 336 return e.Error() 337 } 338 if err == (*Error)(nil) { 339 return Success 340 } 341 // For cases of error chains, err.Error() will print the entire chain, 342 // including the current error and the nested error messages, in an appropriate format. 343 if err.Unwrap() != nil { 344 return err.Error() 345 } 346 return err.Msg 347 }