github.com/jurado-dev/errors@v1.2.10/error.go (about) 1 package errors 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "regexp" 7 "runtime" 8 ) 9 10 type Err struct { 11 Cause string `json:"cause"` 12 Message string `json:"message"` 13 StackMessage string `json:"stack_message"` 14 Trace ErrTrace `json:"trace"` 15 Stack []ErrTrace `json:"stack"` 16 Wrapped error `json:"-"` 17 Code int `json:"code"` 18 } 19 20 type ErrTrace struct { 21 File string `json:"file"` 22 Function string `json:"function"` 23 Line int `json:"line"` 24 } 25 26 // Error implements the interface 27 func (e *Err) Error() string { 28 29 output := fmt.Sprintf("Info: %s", e.Message) 30 if e.Trace.Line != 0 { 31 32 cause := e.Cause 33 if len(cause) > 200 { 34 cause = cause[:200] + "..." 35 } 36 37 output = fmt.Sprintf("Cause: %s | Info: %s | Line: %d | Function: %s", cause, e.Message, e.Trace.Line, e.Trace.Function) 38 } 39 40 return output 41 } 42 43 func extractErr(err error) Err { 44 45 switch e := err.(type) { 46 case *Internal: 47 return e.Err 48 case *NotFound: 49 return e.Err 50 case *Conflict: 51 return e.Err 52 case *BadRequest: 53 return e.Err 54 case *Unauthorized: 55 return e.Err 56 case *Fatal: 57 return e.Err 58 case *NoContent: 59 return e.Err 60 case *Timeout: 61 return e.Err 62 } 63 64 return Err{} 65 } 66 67 // Stack adds a trace to the stack slice 68 func Stack(err error, trace ErrTrace) error { 69 70 if err == nil { 71 return err 72 } 73 74 switch e := err.(type) { 75 case *Internal: 76 e.Err.Stack = append(e.Err.Stack, trace) 77 return e 78 case *NotFound: 79 e.Err.Stack = append(e.Err.Stack, trace) 80 return e 81 case *Conflict: 82 e.Err.Stack = append(e.Err.Stack, trace) 83 return e 84 case *BadRequest: 85 e.Err.Stack = append(e.Err.Stack, trace) 86 return e 87 case *Unauthorized: 88 e.Err.Stack = append(e.Err.Stack, trace) 89 return e 90 case *Fatal: 91 e.Err.Stack = append(e.Err.Stack, trace) 92 return e 93 case *NoContent: 94 e.Err.Stack = append(e.Err.Stack, trace) 95 return e 96 case *Timeout: 97 e.Err.Stack = append(e.Err.Stack, trace) 98 return e 99 } 100 101 return err 102 } 103 104 func StackMsg(err error, msg string, trace ErrTrace) error { 105 if err == nil { 106 return err 107 } 108 109 switch e := err.(type) { 110 case *Internal: 111 e.Err.Stack = append(e.Err.Stack, trace) 112 e.StackMessage = msg 113 return e 114 case *NotFound: 115 e.Err.Stack = append(e.Err.Stack, trace) 116 e.StackMessage = msg 117 return e 118 case *Conflict: 119 e.Err.Stack = append(e.Err.Stack, trace) 120 e.StackMessage = msg 121 return e 122 case *BadRequest: 123 e.Err.Stack = append(e.Err.Stack, trace) 124 e.StackMessage = msg 125 return e 126 case *Unauthorized: 127 e.Err.Stack = append(e.Err.Stack, trace) 128 e.StackMessage = msg 129 return e 130 case *Fatal: 131 e.Err.Stack = append(e.Err.Stack, trace) 132 e.StackMessage = msg 133 return e 134 case *NoContent: 135 e.Err.Stack = append(e.Err.Stack, trace) 136 e.StackMessage = msg 137 return e 138 case *Timeout: 139 e.Err.Stack = append(e.Err.Stack, trace) 140 e.StackMessage = msg 141 return e 142 } 143 return err 144 } 145 146 // ErrorF returns the full error information 147 func ErrorF(err error) string { 148 149 if err == nil { 150 return "" 151 } 152 153 e := extractErr(err) 154 if e.Cause == "" && e.Message == "" { 155 return err.Error() 156 } 157 158 var stackTrace string 159 160 traceFormat := "> Line=%-4d | Function=%-40s | File=%-30s" 161 162 for _, stack := range e.Stack { 163 stackTrace += fmt.Sprintf("\n"+traceFormat, stack.Line, stack.Function, stack.File) 164 } 165 166 return fmt.Sprintf("\n Full error information:\n- Cause: %s\n- Info: %s\n- Stack msg: %s\n- Error code: %d\n- Stack trace: %s", e.Cause, e.Message, e.StackMessage, e.Code, stackTrace) 167 } 168 169 // Unwrap returns the original error 170 func Unwrap(err error) error { 171 172 if err == nil { 173 return err 174 } 175 176 e := extractErr(err) 177 if e.Cause == "" && e.Message == "" { 178 return err 179 } 180 181 return e.Wrapped 182 } 183 184 func GetCause(err error) string { 185 if err == nil { 186 return "" 187 } 188 e := extractErr(err) 189 if e.Cause == "" && e.Message != "" { 190 return e.Message 191 } else if e.Cause == "" && e.Message == "" { 192 return err.Error() 193 } 194 return e.Cause 195 } 196 197 func GetMessage(err error) string { 198 if err == nil { 199 return "" 200 } 201 e := extractErr(err) 202 if e.Message == "" { 203 return err.Error() 204 } 205 return e.Message 206 } 207 208 func GetTrace(err error) ErrTrace { 209 if err == nil { 210 return ErrTrace{} 211 } 212 e := extractErr(err) 213 if e.Trace.File == "" { 214 return ErrTrace{} 215 } 216 return e.Trace 217 } 218 219 func GetStack(err error) []ErrTrace { 220 if err == nil { 221 return nil 222 } 223 e := extractErr(err) 224 if len(e.Stack) == 0 { 225 return []ErrTrace{} 226 } 227 return e.Stack 228 } 229 230 func GetStackJson(err error) string { 231 if err == nil { 232 return "" 233 } 234 e := extractErr(err) 235 if len(e.Stack) == 0 { 236 return "{}" 237 } 238 239 encoded, _ := json.Marshal(e.Stack) 240 241 return string(encoded) 242 } 243 244 func GetWrapped(err error) error { 245 if err == nil { 246 return nil 247 } 248 e := extractErr(err) 249 if e.Wrapped == nil { 250 return err 251 } 252 return e.Wrapped 253 } 254 255 func GetCode(err error) int { 256 if err == nil { 257 return 0 258 } 259 e := extractErr(err) 260 if e.Code == 0 { 261 if IsNotFound(err) { 262 return 404 263 } 264 if IsUnauthorized(err) { 265 return 403 266 } 267 if IsBadRequest(err) { 268 return 400 269 } 270 if IsInternal(err) || IsFatal(err) { 271 return 500 272 } 273 if IsConflict(err) { 274 return 409 275 } 276 if IsNoContent(err) { 277 return 204 278 } 279 } 280 return e.Code 281 } 282 283 func Trace() ErrTrace { 284 pc := make([]uintptr, 10) 285 runtime.Callers(2, pc) 286 function := runtime.FuncForPC(pc[0]) 287 file, line := function.FileLine(pc[0]) 288 289 // matching only the file name 290 rgx, err := regexp.Compile(`(?i)/([\w\d_+*()\[\]%=\-]+\.\w+)$`) 291 if err == nil { 292 matches := rgx.FindStringSubmatch(file) 293 if len(matches) > 0 { 294 file = matches[1] 295 } 296 } 297 298 funcName := function.Name() 299 rgx, err = regexp.Compile(`(?i)(/[\w\d_*().\-]+$)`) 300 if err == nil { 301 matches := rgx.FindStringSubmatch(funcName) 302 if len(matches) > 0 { 303 funcName = matches[1] 304 } 305 } 306 return ErrTrace{Line: line, File: file, Function: funcName} 307 }