90 lines
2.1 KiB
Go
90 lines
2.1 KiB
Go
package main
|
|
|
|
import (
|
|
"runtime"
|
|
|
|
"github.com/getsentry/raven-go"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
func NewRavenStackTrace(client *raven.Client, myerr error, skip int) *raven.Stacktrace {
|
|
st := getErrorStackTraceConverted(myerr, 3, client.IncludePaths())
|
|
if st == nil {
|
|
st = raven.NewStacktrace(skip, 3, client.IncludePaths())
|
|
}
|
|
return st
|
|
}
|
|
|
|
func getErrorStackTraceConverted(err error, context int, appPackagePrefixes []string) *raven.Stacktrace {
|
|
st := getErrorCauseStackTrace(err)
|
|
if st == nil {
|
|
return nil
|
|
}
|
|
return convertStackTrace(st, context, appPackagePrefixes)
|
|
}
|
|
|
|
func getErrorCauseStackTrace(err error) errors.StackTrace {
|
|
// This code is inspired by github.com/pkg/errors.Cause().
|
|
var st errors.StackTrace
|
|
for err != nil {
|
|
s := getErrorStackTrace(err)
|
|
if s != nil {
|
|
st = s
|
|
}
|
|
err = getErrorCause(err)
|
|
}
|
|
return st
|
|
}
|
|
|
|
func convertStackTrace(st errors.StackTrace, context int, appPackagePrefixes []string) *raven.Stacktrace {
|
|
// This code is borrowed from github.com/getsentry/raven-go.NewStacktrace().
|
|
var frames []*raven.StacktraceFrame
|
|
for _, f := range st {
|
|
frame := convertFrame(f, context, appPackagePrefixes)
|
|
if frame != nil {
|
|
frames = append(frames, frame)
|
|
}
|
|
}
|
|
if len(frames) == 0 {
|
|
return nil
|
|
}
|
|
for i, j := 0, len(frames)-1; i < j; i, j = i+1, j-1 {
|
|
frames[i], frames[j] = frames[j], frames[i]
|
|
}
|
|
return &raven.Stacktrace{Frames: frames}
|
|
}
|
|
|
|
func convertFrame(f errors.Frame, context int, appPackagePrefixes []string) *raven.StacktraceFrame {
|
|
// This code is borrowed from github.com/pkg/errors.Frame.
|
|
pc := uintptr(f) - 1
|
|
fn := runtime.FuncForPC(pc)
|
|
var file string
|
|
var line int
|
|
if fn != nil {
|
|
file, line = fn.FileLine(pc)
|
|
} else {
|
|
file = "unknown"
|
|
}
|
|
return raven.NewStacktraceFrame(pc, file, line, context, appPackagePrefixes)
|
|
}
|
|
|
|
func getErrorStackTrace(err error) errors.StackTrace {
|
|
ster, ok := err.(interface {
|
|
StackTrace() errors.StackTrace
|
|
})
|
|
if !ok {
|
|
return nil
|
|
}
|
|
return ster.StackTrace()
|
|
}
|
|
|
|
func getErrorCause(err error) error {
|
|
cer, ok := err.(interface {
|
|
Cause() error
|
|
})
|
|
if !ok {
|
|
return nil
|
|
}
|
|
return cer.Cause()
|
|
}
|