github.com/retailcrm/mg-bot-helper@v0.0.0-20201229112329-a17255681a84/src/stacktrace.go (about) 1 package main 2 3 import ( 4 "runtime" 5 6 "github.com/getsentry/raven-go" 7 "github.com/pkg/errors" 8 ) 9 10 func NewRavenStackTrace(client *raven.Client, myerr error, skip int) *raven.Stacktrace { 11 st := getErrorStackTraceConverted(myerr, 3, client.IncludePaths()) 12 if st == nil { 13 st = raven.NewStacktrace(skip, 3, client.IncludePaths()) 14 } 15 return st 16 } 17 18 func getErrorStackTraceConverted(err error, context int, appPackagePrefixes []string) *raven.Stacktrace { 19 st := getErrorCauseStackTrace(err) 20 if st == nil { 21 return nil 22 } 23 return convertStackTrace(st, context, appPackagePrefixes) 24 } 25 26 func getErrorCauseStackTrace(err error) errors.StackTrace { 27 // This code is inspired by github.com/pkg/errors.Cause(). 28 var st errors.StackTrace 29 for err != nil { 30 s := getErrorStackTrace(err) 31 if s != nil { 32 st = s 33 } 34 err = getErrorCause(err) 35 } 36 return st 37 } 38 39 func convertStackTrace(st errors.StackTrace, context int, appPackagePrefixes []string) *raven.Stacktrace { 40 // This code is borrowed from github.com/getsentry/raven-go.NewStacktrace(). 41 var frames []*raven.StacktraceFrame 42 for _, f := range st { 43 frame := convertFrame(f, context, appPackagePrefixes) 44 if frame != nil { 45 frames = append(frames, frame) 46 } 47 } 48 if len(frames) == 0 { 49 return nil 50 } 51 for i, j := 0, len(frames)-1; i < j; i, j = i+1, j-1 { 52 frames[i], frames[j] = frames[j], frames[i] 53 } 54 return &raven.Stacktrace{Frames: frames} 55 } 56 57 func convertFrame(f errors.Frame, context int, appPackagePrefixes []string) *raven.StacktraceFrame { 58 // This code is borrowed from github.com/pkg/errors.Frame. 59 pc := uintptr(f) - 1 60 fn := runtime.FuncForPC(pc) 61 var file string 62 var line int 63 if fn != nil { 64 file, line = fn.FileLine(pc) 65 } else { 66 file = "unknown" 67 } 68 return raven.NewStacktraceFrame(pc, file, line, context, appPackagePrefixes) 69 } 70 71 func getErrorStackTrace(err error) errors.StackTrace { 72 ster, ok := err.(interface { 73 StackTrace() errors.StackTrace 74 }) 75 if !ok { 76 return nil 77 } 78 return ster.StackTrace() 79 } 80 81 func getErrorCause(err error) error { 82 cer, ok := err.(interface { 83 Cause() error 84 }) 85 if !ok { 86 return nil 87 } 88 return cer.Cause() 89 }