github.com/lulzWill/go-agent@v2.1.2+incompatible/_integrations/nrpkgerrors/nrpkgerrors.go (about) 1 // Package nrpkgerrors introduces support for github.com/pkg/errors. 2 package nrpkgerrors 3 4 import ( 5 "fmt" 6 7 newrelic "github.com/lulzWill/go-agent" 8 "github.com/lulzWill/go-agent/internal" 9 "github.com/pkg/errors" 10 ) 11 12 func init() { internal.TrackUsage("integration", "pkg-errors") } 13 14 type nrpkgerror struct { 15 error 16 } 17 18 // stackTracer is an error that also knows about its StackTrace. 19 // All wrapped errors from github.com/pkg/errors implement this interface. 20 type stackTracer interface { 21 StackTrace() errors.StackTrace 22 } 23 24 func deepestStackTrace(err error) errors.StackTrace { 25 var last stackTracer 26 for err != nil { 27 if err, ok := err.(stackTracer); ok { 28 last = err 29 } 30 cause, ok := err.(interface { 31 Cause() error 32 }) 33 if !ok { 34 break 35 } 36 err = cause.Cause() 37 } 38 39 if last == nil { 40 return nil 41 } 42 return last.StackTrace() 43 } 44 45 func transformStackTrace(orig errors.StackTrace) []uintptr { 46 st := make([]uintptr, len(orig)) 47 for i, frame := range orig { 48 st[i] = uintptr(frame) 49 } 50 return st 51 } 52 53 func (e nrpkgerror) StackTrace() []uintptr { 54 st := deepestStackTrace(e.error) 55 if nil == st { 56 return nil 57 } 58 return transformStackTrace(st) 59 } 60 61 func (e nrpkgerror) ErrorClass() string { 62 if ec, ok := e.error.(newrelic.ErrorClasser); ok { 63 return ec.ErrorClass() 64 } 65 cause := errors.Cause(e.error) 66 if ec, ok := cause.(newrelic.ErrorClasser); ok { 67 return ec.ErrorClass() 68 } 69 return fmt.Sprintf("%T", cause) 70 } 71 72 // Wrap wraps an error from github.com/pkg/errors so that the stacktrace 73 // provided by the error matches the format expected by the newrelic package. 74 func Wrap(e error) error { 75 return nrpkgerror{e} 76 }