1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| package util
import ( "fmt" "strings"
"github.com/pkg/errors" "github.com/samber/lo" )
type stackTracer interface { StackTrace() errors.StackTrace }
type unwrappable interface { Unwrap() error }
type ErrorFrame struct { Key string Loc string }
type ErrorDetail struct { Type string `json:"type"` Message string `json:"message"` StackTrace errors.StackTrace `json:"-"` Cause *ErrorDetail `json:"cause,omitempty"` }
func GetErrorDetail(e error) *ErrorDetail { var stack errors.StackTrace
//nolint:errorlint t, ok := e.(stackTracer) if ok { stack = t.StackTrace() }
var cause *ErrorDetail
//nolint:errorlint u, ok := e.(unwrappable) if ok { cause = GetErrorDetail(u.Unwrap()) }
msg := KeyError if e != nil { msg = e.Error() }
return &ErrorDetail{ Type: KeyError, Message: msg, StackTrace: stack, Cause: cause, } }
func TraceDetail(trace errors.StackTrace) []ErrorFrame { s := fmt.Sprintf("%+v", trace) lines := StringSplitLines(s) var validLines []string
lo.ForEach(lines, func(line string, _ int) { l := strings.TrimSpace(line) if len(l) > 0 { validLines = append(validLines, l) } })
var ret []ErrorFrame for i := 0; i < len(validLines)-1; i += 2 { f := ErrorFrame{Key: validLines[i], Loc: validLines[i+1]} ret = append(ret, f) } return ret }
func ErrorMerge(errs ...error) error { switch len(errs) { case 0: return nil case 1: return errs[0] } msg := lo.Map(errs, func(e error, _ int) string { return e.Error() }) return errors.Wrapf(errs[0], strings.Join(msg, ", ")) }
|