github.com/newrelic/go-agent@v3.26.0+incompatible/_integrations/nrpkgerrors/nrpkgerrors.go (about) 1 // Copyright 2020 New Relic Corporation. All rights reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 // Package nrpkgerrors introduces support for https://github.com/pkg/errors. 5 // 6 // This package improves the class and stack-trace fields of pkg/error errors 7 // when they are recorded with Transaction.NoticeError. 8 // 9 package nrpkgerrors 10 11 import ( 12 "fmt" 13 14 newrelic "github.com/newrelic/go-agent" 15 "github.com/newrelic/go-agent/internal" 16 "github.com/pkg/errors" 17 ) 18 19 func init() { internal.TrackUsage("integration", "pkg-errors") } 20 21 type nrpkgerror struct { 22 error 23 } 24 25 // stackTracer is an error that also knows about its StackTrace. 26 // All wrapped errors from github.com/pkg/errors implement this interface. 27 type stackTracer interface { 28 StackTrace() errors.StackTrace 29 } 30 31 func deepestStackTrace(err error) errors.StackTrace { 32 var last stackTracer 33 for err != nil { 34 if err, ok := err.(stackTracer); ok { 35 last = err 36 } 37 cause, ok := err.(interface { 38 Cause() error 39 }) 40 if !ok { 41 break 42 } 43 err = cause.Cause() 44 } 45 46 if last == nil { 47 return nil 48 } 49 return last.StackTrace() 50 } 51 52 func transformStackTrace(orig errors.StackTrace) []uintptr { 53 st := make([]uintptr, len(orig)) 54 for i, frame := range orig { 55 st[i] = uintptr(frame) 56 } 57 return st 58 } 59 60 func (e nrpkgerror) StackTrace() []uintptr { 61 st := deepestStackTrace(e.error) 62 if nil == st { 63 return nil 64 } 65 return transformStackTrace(st) 66 } 67 68 func (e nrpkgerror) ErrorClass() string { 69 if ec, ok := e.error.(newrelic.ErrorClasser); ok { 70 return ec.ErrorClass() 71 } 72 cause := errors.Cause(e.error) 73 if ec, ok := cause.(newrelic.ErrorClasser); ok { 74 return ec.ErrorClass() 75 } 76 return fmt.Sprintf("%T", cause) 77 } 78 79 // Wrap wraps a pkg/errors error so that when noticed by 80 // newrelic.Transaction.NoticeError it gives an improved stacktrace and class 81 // type. 82 func Wrap(e error) error { 83 return nrpkgerror{e} 84 }