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