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  }