github.com/v2fly/v2ray-core/v4@v4.45.2/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/v2fly/v2ray-core/v4/common/log" 10 "github.com/v2fly/v2ray-core/v4/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 path = strings.TrimPrefix(path, "github.com/v2fly/v2ray-core/v4/") 42 path = strings.TrimPrefix(path, "github.com/v2fly/v2ray-core/v4") 43 return path 44 } 45 46 // Error implements error.Error(). 47 func (err *Error) Error() string { 48 builder := strings.Builder{} 49 for _, prefix := range err.prefix { 50 builder.WriteByte('[') 51 builder.WriteString(serial.ToString(prefix)) 52 builder.WriteString("] ") 53 } 54 55 path := err.pkgPath() 56 if len(path) > 0 { 57 builder.WriteString(path) 58 builder.WriteString(": ") 59 } 60 61 msg := serial.Concat(err.message...) 62 builder.WriteString(msg) 63 64 if err.inner != nil { 65 builder.WriteString(" > ") 66 builder.WriteString(err.inner.Error()) 67 } 68 69 return builder.String() 70 } 71 72 // Inner implements hasInnerError.Inner() 73 func (err *Error) Inner() error { 74 if err.inner == nil { 75 return nil 76 } 77 return err.inner 78 } 79 80 func (err *Error) Base(e error) *Error { 81 err.inner = e 82 return err 83 } 84 85 func (err *Error) atSeverity(s log.Severity) *Error { 86 err.severity = s 87 return err 88 } 89 90 func (err *Error) Severity() log.Severity { 91 if err.inner == nil { 92 return err.severity 93 } 94 95 if s, ok := err.inner.(hasSeverity); ok { 96 as := s.Severity() 97 if as < err.severity { 98 return as 99 } 100 } 101 102 return err.severity 103 } 104 105 // AtDebug sets the severity to debug. 106 func (err *Error) AtDebug() *Error { 107 return err.atSeverity(log.Severity_Debug) 108 } 109 110 // AtInfo sets the severity to info. 111 func (err *Error) AtInfo() *Error { 112 return err.atSeverity(log.Severity_Info) 113 } 114 115 // AtWarning sets the severity to warning. 116 func (err *Error) AtWarning() *Error { 117 return err.atSeverity(log.Severity_Warning) 118 } 119 120 // AtError sets the severity to error. 121 func (err *Error) AtError() *Error { 122 return err.atSeverity(log.Severity_Error) 123 } 124 125 // String returns the string representation of this error. 126 func (err *Error) String() string { 127 return err.Error() 128 } 129 130 // WriteToLog writes current error into log. 131 func (err *Error) WriteToLog(opts ...ExportOption) { 132 var holder ExportOptionHolder 133 134 for _, opt := range opts { 135 opt(&holder) 136 } 137 138 if holder.SessionID > 0 { 139 err.prefix = append(err.prefix, holder.SessionID) 140 } 141 142 log.Record(&log.GeneralMessage{ 143 Severity: GetSeverity(err), 144 Content: err, 145 }) 146 } 147 148 type ExportOptionHolder struct { 149 SessionID uint32 150 } 151 152 type ExportOption func(*ExportOptionHolder) 153 154 // New returns a new error object with message formed from given arguments. 155 func New(msg ...interface{}) *Error { 156 return &Error{ 157 message: msg, 158 severity: log.Severity_Info, 159 } 160 } 161 162 // Cause returns the root cause of this error. 163 func Cause(err error) error { 164 if err == nil { 165 return nil 166 } 167 L: 168 for { 169 switch inner := err.(type) { 170 case hasInnerError: 171 if inner.Inner() == nil { 172 break L 173 } 174 err = inner.Inner() 175 case *os.PathError: 176 if inner.Err == nil { 177 break L 178 } 179 err = inner.Err 180 case *os.SyscallError: 181 if inner.Err == nil { 182 break L 183 } 184 err = inner.Err 185 default: 186 break L 187 } 188 } 189 return err 190 } 191 192 // GetSeverity returns the actual severity of the error, including inner errors. 193 func GetSeverity(err error) log.Severity { 194 if s, ok := err.(hasSeverity); ok { 195 return s.Severity() 196 } 197 return log.Severity_Info 198 }