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