github.com/xraypb/Xray-core@v1.8.1/common/errors/errors.go (about) 1 // Package errors is a drop-in replacement for Golang lib 'errors'. 2 package errors // import "github.com/xraypb/Xray-core/common/errors" 3 4 import ( 5 "reflect" 6 "strings" 7 8 "github.com/xraypb/Xray-core/common/log" 9 "github.com/xraypb/Xray-core/common/serial" 10 ) 11 12 const trim = len("github.com/xraypb/Xray-core/") 13 14 type hasInnerError interface { 15 // Unwrap returns the underlying error of this one. 16 Unwrap() error 17 } 18 19 type hasSeverity interface { 20 Severity() log.Severity 21 } 22 23 // Error is an error object with underlying error. 24 type Error struct { 25 pathObj interface{} 26 prefix []interface{} 27 message []interface{} 28 inner error 29 severity log.Severity 30 } 31 32 func (err *Error) WithPathObj(obj interface{}) *Error { 33 err.pathObj = obj 34 return err 35 } 36 37 func (err *Error) pkgPath() string { 38 if err.pathObj == nil { 39 return "" 40 } 41 path := reflect.TypeOf(err.pathObj).PkgPath() 42 if len(path) >= trim { 43 return path[trim:] 44 } 45 return path 46 } 47 48 // Error implements error.Error(). 49 func (err *Error) Error() string { 50 builder := strings.Builder{} 51 for _, prefix := range err.prefix { 52 builder.WriteByte('[') 53 builder.WriteString(serial.ToString(prefix)) 54 builder.WriteString("] ") 55 } 56 57 path := err.pkgPath() 58 if len(path) > 0 { 59 builder.WriteString(path) 60 builder.WriteString(": ") 61 } 62 63 msg := serial.Concat(err.message...) 64 builder.WriteString(msg) 65 66 if err.inner != nil { 67 builder.WriteString(" > ") 68 builder.WriteString(err.inner.Error()) 69 } 70 71 return builder.String() 72 } 73 74 // Unwrap implements hasInnerError.Unwrap() 75 func (err *Error) Unwrap() error { 76 if err.inner == nil { 77 return nil 78 } 79 return err.inner 80 } 81 82 func (err *Error) Base(e error) *Error { 83 err.inner = e 84 return err 85 } 86 87 func (err *Error) atSeverity(s log.Severity) *Error { 88 err.severity = s 89 return err 90 } 91 92 func (err *Error) Severity() log.Severity { 93 if err.inner == nil { 94 return err.severity 95 } 96 97 if s, ok := err.inner.(hasSeverity); ok { 98 as := s.Severity() 99 if as < err.severity { 100 return as 101 } 102 } 103 104 return err.severity 105 } 106 107 // AtDebug sets the severity to debug. 108 func (err *Error) AtDebug() *Error { 109 return err.atSeverity(log.Severity_Debug) 110 } 111 112 // AtInfo sets the severity to info. 113 func (err *Error) AtInfo() *Error { 114 return err.atSeverity(log.Severity_Info) 115 } 116 117 // AtWarning sets the severity to warning. 118 func (err *Error) AtWarning() *Error { 119 return err.atSeverity(log.Severity_Warning) 120 } 121 122 // AtError sets the severity to error. 123 func (err *Error) AtError() *Error { 124 return err.atSeverity(log.Severity_Error) 125 } 126 127 // String returns the string representation of this error. 128 func (err *Error) String() string { 129 return err.Error() 130 } 131 132 // WriteToLog writes current error into log. 133 func (err *Error) WriteToLog(opts ...ExportOption) { 134 var holder ExportOptionHolder 135 136 for _, opt := range opts { 137 opt(&holder) 138 } 139 140 if holder.SessionID > 0 { 141 err.prefix = append(err.prefix, holder.SessionID) 142 } 143 144 log.Record(&log.GeneralMessage{ 145 Severity: GetSeverity(err), 146 Content: err, 147 }) 148 } 149 150 type ExportOptionHolder struct { 151 SessionID uint32 152 } 153 154 type ExportOption func(*ExportOptionHolder) 155 156 // New returns a new error object with message formed from given arguments. 157 func New(msg ...interface{}) *Error { 158 return &Error{ 159 message: msg, 160 severity: log.Severity_Info, 161 } 162 } 163 164 // Cause returns the root cause of this error. 165 func Cause(err error) error { 166 if err == nil { 167 return nil 168 } 169 L: 170 for { 171 switch inner := err.(type) { 172 case hasInnerError: 173 if inner.Unwrap() == nil { 174 break L 175 } 176 err = inner.Unwrap() 177 default: 178 break L 179 } 180 } 181 return err 182 } 183 184 // GetSeverity returns the actual severity of the error, including inner errors. 185 func GetSeverity(err error) log.Severity { 186 if s, ok := err.(hasSeverity); ok { 187 return s.Severity() 188 } 189 return log.Severity_Info 190 }