github.com/15mga/kiwi@v0.0.2-0.20240324021231-b95d5c3ac751/util/err.go (about)

     1  package util
     2  
     3  import (
     4  	"regexp"
     5  	"runtime"
     6  	"strconv"
     7  )
     8  
     9  const (
    10  	EcMin TErrCode = iota + 60000
    11  	EcNil
    12  	EcRecover
    13  	EcWrongType
    14  	EcBusy
    15  	EcNotEnough
    16  	EcNoAuth
    17  	EcTimeout
    18  	EcClosed
    19  	EcOpened
    20  	EcEmpty
    21  	EcBadHead
    22  	EcBadPacket
    23  	EcExist
    24  	EcNotExist
    25  	EcMarshallErr
    26  	EcUnmarshallErr
    27  	EcIllegalOp
    28  	EcIllegalConn
    29  	EcTooManyConn
    30  	EcParamsErr
    31  	EcParseErr
    32  	EcIo
    33  	EcOutOfRange
    34  	EcTooLong
    35  	EcTooMuch
    36  	EcLengthErr
    37  	EcNotExistAgent
    38  	EcSendErr
    39  	EcReceiveErr
    40  	EcAcceptErr
    41  	EcConnectErr
    42  	EcListenErr
    43  	EcAddrErr
    44  	EcUnavailable
    45  	EcNotImplement
    46  	EcType
    47  	EcWriteFail
    48  	EcFail
    49  	EcTooSlow
    50  	EcServiceErr
    51  	EcDbErr
    52  	EcRedisErr
    53  	EcEtcdErr
    54  )
    55  
    56  var (
    57  	_ErrCodeToString = map[TErrCode]string{
    58  		EcNil:           "object_nil",
    59  		EcRecover:       "recover",
    60  		EcWrongType:     "wrong_type",
    61  		EcBusy:          "busy",
    62  		EcNotEnough:     "not_enough",
    63  		EcNoAuth:        "no_auth",
    64  		EcTimeout:       "timeout",
    65  		EcClosed:        "closed",
    66  		EcOpened:        "opened",
    67  		EcEmpty:         "empty",
    68  		EcBadHead:       "bad_head",
    69  		EcBadPacket:     "bad_packet",
    70  		EcExist:         "exist",
    71  		EcNotExist:      "not_exist",
    72  		EcMarshallErr:   "marshall_error",
    73  		EcUnmarshallErr: "unmarshall_error",
    74  		EcIllegalOp:     "illegal_operation",
    75  		EcIllegalConn:   "illegal_conn",
    76  		EcTooManyConn:   "too_many_conn",
    77  		EcParamsErr:     "args_error",
    78  		EcParseErr:      "parse_error",
    79  		EcIo:            "io_error",
    80  		EcOutOfRange:    "out_of_range",
    81  		EcTooLong:       "too_long",
    82  		EcTooMuch:       "too_much",
    83  		EcLengthErr:     "length_wrong",
    84  		EcNotExistAgent: "not_exist_agent",
    85  		EcSendErr:       "send_error",
    86  		EcReceiveErr:    "receive_error",
    87  		EcAcceptErr:     "accept_error",
    88  		EcConnectErr:    "connect_error",
    89  		EcListenErr:     "listen_error",
    90  		EcServiceErr:    "service_error",
    91  		EcDbErr:         "database_error",
    92  		EcRedisErr:      "redis_wrong",
    93  		EcEtcdErr:       "etcd_wrong",
    94  		EcAddrErr:       "get_addr_error",
    95  		EcUnavailable:   "unavailable",
    96  		EcNotImplement:  "not_implement",
    97  		EcType:          "err_type",
    98  		EcWriteFail:     "write_fail",
    99  		EcFail:          "fail_code",
   100  		EcTooSlow:       "too_slow",
   101  	}
   102  )
   103  
   104  func SetErrCodeToStr(ec TErrCode, str string) {
   105  	_ErrCodeToString[ec] = str
   106  }
   107  
   108  func ErrCodeToStr(ec TErrCode) string {
   109  	str, ok := _ErrCodeToString[ec]
   110  	if ok {
   111  		return str
   112  	}
   113  	return strconv.FormatInt(int64(ec), 10)
   114  }
   115  
   116  func WrapErr(code TErrCode, e error) *Err {
   117  	if e == nil {
   118  		return &Err{code: code, stack: GetStack(3)}
   119  	}
   120  	return &Err{code: code, stack: GetStack(3), params: M{"error": e.Error()}}
   121  }
   122  
   123  func NewErr(code TErrCode, params M) *Err {
   124  	return &Err{code: code, stack: GetStack(3), params: params}
   125  }
   126  
   127  func NewNoStackErr(code TErrCode, params M) *Err {
   128  	return &Err{code: code, stack: nil, params: params}
   129  }
   130  
   131  func NewErrWithStack(code TErrCode, stack []byte, params M) *Err {
   132  	return &Err{code: code, stack: stack, params: params}
   133  }
   134  
   135  type Err struct {
   136  	code   TErrCode
   137  	stack  []byte
   138  	params M
   139  }
   140  
   141  func (e *Err) Code() TErrCode {
   142  	return e.code
   143  }
   144  
   145  func (e *Err) ToBytes() []byte {
   146  	if e.params == nil {
   147  		e.params = map[string]any{}
   148  	}
   149  	e.params["code"] = e.code
   150  	if e.stack != nil {
   151  		e.params["stack"] = BytesToStr(e.stack)
   152  	}
   153  	bytes, _ := JsonMarshal(e.params)
   154  	return bytes
   155  }
   156  
   157  func (e *Err) Error() string {
   158  	err, ok := e.params["error"]
   159  	if ok {
   160  		return err.(string)
   161  	}
   162  	return BytesToStr(e.ToBytes())
   163  }
   164  
   165  func (e *Err) Params() M {
   166  	return e.params
   167  }
   168  
   169  func (e *Err) Stack() []byte {
   170  	return e.stack
   171  }
   172  
   173  func (e *Err) IsNoStack() bool {
   174  	return e.stack == nil
   175  }
   176  
   177  func (e *Err) AddParam(k string, v any) {
   178  	if e.params == nil {
   179  		e.params = map[string]any{}
   180  	}
   181  	e.params[k] = v
   182  }
   183  
   184  func (e *Err) GetParam(k string) (v any, ok bool) {
   185  	if e.params == nil {
   186  		return nil, false
   187  	}
   188  	v, ok = e.params[k]
   189  	return
   190  }
   191  
   192  func (e *Err) AddParams(params M) {
   193  	if e.params == nil {
   194  		e.params = map[string]any{}
   195  	}
   196  	for k, v := range params {
   197  		e.params[k] = v
   198  	}
   199  }
   200  
   201  func (e *Err) UpdateParam(k string, action AnyBoolToAnyBool) {
   202  	if e.params == nil {
   203  		e.params = map[string]any{}
   204  	}
   205  	ov, ok := e.params[k]
   206  	v, ok := action(ov, ok)
   207  	if ok {
   208  		e.params[k] = v
   209  	} else {
   210  		delete(e.params, k)
   211  	}
   212  }
   213  
   214  func (e *Err) String() string {
   215  	return ErrCodeToStr(e.code)
   216  }
   217  
   218  func GetStack(skip int) []byte {
   219  	const depth = 16
   220  	var rpc [depth]uintptr
   221  	n := runtime.Callers(skip, rpc[:])
   222  	if n < 1 {
   223  		return nil
   224  	}
   225  	frames := runtime.CallersFrames(rpc[:])
   226  
   227  	var buffer ByteBuffer
   228  	buffer.InitCap(256)
   229  	for i := 0; i < StackMaxDeep; i++ {
   230  		frame, ok := frames.Next()
   231  		if !ok {
   232  			break
   233  		}
   234  		buffer.WUint8('\n')
   235  		buffer.WUint8('\t')
   236  		buffer.WStringNoLen(LogTrim(frame.File))
   237  		buffer.WUint8(':')
   238  		buffer.WStringNoLen(strconv.Itoa(frame.Line))
   239  	}
   240  	return buffer.All()
   241  }
   242  
   243  var (
   244  	StackMaxDeep = 8
   245  	LogPrefix    = ".."
   246  	LogReg       = regexp.MustCompile(`(\/.+\.(com)|(org))|(\/.+go\d{1}\.\d{1,2}.\d{1,2}|/src)`)
   247  )
   248  
   249  func LogTrim(file string) string {
   250  	s := LogReg.FindStringIndex(file)
   251  	if len(s) > 0 {
   252  		return LogPrefix + file[s[1]:]
   253  	}
   254  	return file
   255  }