91 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package rollbar
 | |
| 
 | |
| import (
 | |
| 	"os"
 | |
| 	"runtime"
 | |
| 	"strings"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	knownFilePathPatterns = []string{
 | |
| 		"github.com/",
 | |
| 		"code.google.com/",
 | |
| 		"bitbucket.org/",
 | |
| 		"launchpad.net/",
 | |
| 	}
 | |
| )
 | |
| 
 | |
| // Frame is a single line of executed code in a Stack.
 | |
| type Frame struct {
 | |
| 	Filename string `json:"filename"`
 | |
| 	Method   string `json:"method"`
 | |
| 	Line     int    `json:"lineno"`
 | |
| }
 | |
| 
 | |
| // Stack represents a stacktrace as a slice of Frames.
 | |
| type Stack []Frame
 | |
| 
 | |
| // BuildStack builds a full stacktrace for the current execution location.
 | |
| func BuildStack(skip int) Stack {
 | |
| 	stack := make(Stack, 0)
 | |
| 
 | |
| 	for i := skip; ; i++ {
 | |
| 		pc, file, line, ok := runtime.Caller(i)
 | |
| 		if !ok {
 | |
| 			break
 | |
| 		}
 | |
| 		file = shortenFilePath(file)
 | |
| 		stack = append(stack, Frame{file, functionName(pc), line})
 | |
| 	}
 | |
| 
 | |
| 	return stack
 | |
| }
 | |
| 
 | |
| // BuildStackWithCallers builds a full stackstrace from the given list of callees.
 | |
| func BuildStackWithCallers(callers []uintptr) Stack {
 | |
| 	stack := make(Stack, 0, len(callers))
 | |
| 
 | |
| 	for _, caller := range callers {
 | |
| 		if fn := runtime.FuncForPC(caller); fn != nil {
 | |
| 			file, line := fn.FileLine(caller)
 | |
| 			stack = append(stack, Frame{shortenFilePath(file), functionNameFromFunc(fn), line})
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return stack
 | |
| }
 | |
| 
 | |
| // Remove un-needed information from the source file path. This makes them
 | |
| // shorter in Rollbar UI as well as making them the same, regardless of the
 | |
| // machine the code was compiled on.
 | |
| //
 | |
| // Examples:
 | |
| //   /usr/local/go/src/pkg/runtime/proc.c -> pkg/runtime/proc.c
 | |
| //   /home/foo/go/src/github.com/rollbar/rollbar.go -> github.com/rollbar/rollbar.go
 | |
| func shortenFilePath(s string) string {
 | |
| 	idx := strings.Index(s, "/src/pkg/")
 | |
| 	if idx != -1 {
 | |
| 		return s[idx+5:]
 | |
| 	}
 | |
| 	for _, pattern := range knownFilePathPatterns {
 | |
| 		idx = strings.Index(s, pattern)
 | |
| 		if idx != -1 {
 | |
| 			return s[idx:]
 | |
| 		}
 | |
| 	}
 | |
| 	return s
 | |
| }
 | |
| 
 | |
| func functionNameFromFunc(fn *runtime.Func) string {
 | |
| 	if fn == nil {
 | |
| 		return "???"
 | |
| 	}
 | |
| 	name := fn.Name()
 | |
| 	end := strings.LastIndex(name, string(os.PathSeparator))
 | |
| 	return name[end+1 : len(name)]
 | |
| }
 | |
| 
 | |
| func functionName(pc uintptr) string {
 | |
| 	return functionNameFromFunc(runtime.FuncForPC(pc))
 | |
| }
 | 
