func NewStacktraceFrame(pc uintptr, fName, file string, line, context int, appPackagePrefixes []string) *StacktraceFrame {
	frame := &StacktraceFrame{AbsolutePath: file, Filename: trimPath(file), Lineno: line, InApp: false}
	frame.Module, frame.Function = functionName(fName)
	if frame.Module == "runtime" && frame.Function == "goexit" {
		return nil
	}
	if frame.Module == "main" {
		frame.InApp = true
	} else {
		for _, prefix := range appPackagePrefixes {
			if strings.HasPrefix(frame.Module, prefix) && !strings.Contains(frame.Module, "vendor") && !strings.Contains(frame.Module, "third_party") {
				frame.InApp = true
			}
		}
	}
	if context > 0 {
		contextLines, lineIdx := sourceCodeLoader.Load(file, line, context)
		if len(contextLines) > 0 {
			for i, line := range contextLines {
				switch {
				case i < lineIdx:
					frame.PreContext = append(frame.PreContext, string(line))
				case i == lineIdx:
					frame.ContextLine = string(line)
				default:
					frame.PostContext = append(frame.PostContext, string(line))
				}
			}
		}
	} else if context == -1 {
		contextLine, _ := sourceCodeLoader.Load(file, line, 0)
		if len(contextLine) > 0 {
			frame.ContextLine = string(contextLine[0])
		}
	}
	return frame
}
Build a single frame using data returned from runtime.Caller.

context is the number of surrounding lines that should be included for context.
Setting context to 3 would try to get seven lines. Setting context to -1 returns
one line with no surrounding context, and 0 returns no context.

appPackagePrefixes is a list of prefixes used to check whether a package should
be considered "in app".
package raven
import (
	"bytes"
	"go/build"
	"io/ioutil"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"github.com/pkg/errors"
)
type Stacktrace struct {
	Frames []*StacktraceFrame `json:"frames"`
}
func (s *Stacktrace) Class() string { return "stacktrace" }
func (s *Stacktrace) Culprit() string {
	for i := len(s.Frames) - 1; i >= 0; i-- {
		frame := s.Frames[i]
		if frame.InApp == true && frame.Module != "" && frame.Function != "" {
			return frame.Module + "." + frame.Function
		}
	}
	return ""
}
type StacktraceFrame struct {
	Filename string `json:"filename,omitempty"`
	Function string `json:"function,omitempty"`
	Module   string `json:"module,omitempty"`
	Lineno       int      `json:"lineno,omitempty"`
	Colno        int      `json:"colno,omitempty"`
	AbsolutePath string   `json:"abs_path,omitempty"`
	ContextLine  string   `json:"context_line,omitempty"`
	PreContext   []string `json:"pre_context,omitempty"`
	PostContext  []string `json:"post_context,omitempty"`
	InApp        bool     `json:"in_app"`
}
func GetOrNewStacktrace(err error, skip int, context int, appPackagePrefixes []string) *Stacktrace {
	stacktracer, errHasStacktrace := err.(interface {
		StackTrace() errors.StackTrace
	})
	if errHasStacktrace {
		var frames []*StacktraceFrame
		for _, f := range stacktracer.StackTrace() {
			pc := uintptr(f) - 1
			fn := runtime.FuncForPC(pc)
			var fName string
			var file string
			var line int
			if fn != nil {
				file, line = fn.FileLine(pc)
				fName = fn.Name()
			} else {
				file = "unknown"
				fName = "unknown"
			}
			frame := NewStacktraceFrame(pc, fName, file, line, context, appPackagePrefixes)
			if frame != nil {
				frames = append([]*StacktraceFrame{frame}, frames...)
			}
		}
		return &Stacktrace{Frames: frames}
	} else {
		return NewStacktrace(skip+1, context, appPackagePrefixes)
	}
}
func NewStacktrace(skip int, context int, appPackagePrefixes []string) *Stacktrace {
	var frames []*StacktraceFrame
	callerPcs := make([]uintptr, 100)
	numCallers := runtime.Callers(skip+2, callerPcs)
	if numCallers == 0 {
		return nil
	}
	callersFrames := runtime.CallersFrames(callerPcs)
	for {
		fr, more := callersFrames.Next()
		if fr.Func != nil {
			frame := NewStacktraceFrame(fr.PC, fr.Function, fr.File, fr.Line, context, appPackagePrefixes)
			if frame != nil {
				frames = append(frames, frame)
			}
		}
		if !more {
			break
		}
	}
	if len(frames) == 0 {
		return nil
	}
	if len(frames) == 1 {
		return &Stacktrace{frames}
	}
	for i, j := 0, len(frames)-1; i < j; i, j = i+1, j-1 {
		frames[i], frames[j] = frames[j], frames[i]
	}
	return &Stacktrace{frames}
}