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  }