86 lines
1.8 KiB
Go
86 lines
1.8 KiB
Go
package stacktrace
|
|
|
|
import (
|
|
"fmt"
|
|
"git.codebau.dev/goblins/commons/pkg/osdep"
|
|
"math"
|
|
"runtime"
|
|
)
|
|
|
|
const NoStatusCode = math.MinInt
|
|
|
|
type ErrorReporter struct {
|
|
EnableStacktraces bool
|
|
}
|
|
|
|
type StackElement struct {
|
|
File string
|
|
FunctionName string
|
|
Line int
|
|
}
|
|
|
|
type ErrorWithStacktrace struct {
|
|
error
|
|
ErrorCode int
|
|
Stack *[]*StackElement
|
|
}
|
|
|
|
func (s *ErrorWithStacktrace) build(enableStackTraces bool) {
|
|
if !enableStackTraces || s == nil || s.error == nil {
|
|
return
|
|
}
|
|
readingCallers := true
|
|
callerIncrement := 1
|
|
var stack []*StackElement
|
|
for readingCallers {
|
|
callerIncrement += 1
|
|
caller, file, line, ok := runtime.Caller(callerIncrement)
|
|
if !ok {
|
|
readingCallers = false
|
|
} else {
|
|
funcName := ""
|
|
if function := runtime.FuncForPC(caller); function != nil {
|
|
funcName = function.Name()
|
|
}
|
|
stack = append(stack, &StackElement{
|
|
File: file,
|
|
FunctionName: funcName,
|
|
Line: line,
|
|
})
|
|
s.Stack = &stack
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *ErrorWithStacktrace) Format() string {
|
|
if s == nil || s.Stack == nil || len(*s.Stack) == 0 {
|
|
return "[no stack trace]"
|
|
}
|
|
out := ""
|
|
lineSep := osdep.GetLineSep()
|
|
for i, se := range *s.Stack {
|
|
out += fmt.Sprintf("%7d | %s:%d%s %s%s", i, se.File, se.Line, lineSep, se.FunctionName, lineSep)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func (s *ErrorWithStacktrace) Stacktrace() *[]*StackElement {
|
|
return s.Stack
|
|
}
|
|
|
|
func (r *ErrorReporter) New(err error) *ErrorWithStacktrace {
|
|
s := &ErrorWithStacktrace{error: err, ErrorCode: NoStatusCode}
|
|
s.build(r.EnableStacktraces)
|
|
return s
|
|
}
|
|
|
|
func (r *ErrorReporter) NewWithErrorCode(errorCode int, err error) *ErrorWithStacktrace {
|
|
s := &ErrorWithStacktrace{error: err, ErrorCode: errorCode}
|
|
s.build(r.EnableStacktraces)
|
|
return s
|
|
}
|
|
|
|
func New(enableStacktraces bool) *ErrorReporter {
|
|
return &ErrorReporter{EnableStacktraces: enableStacktraces}
|
|
}
|