adverr/calltrace.go

54 lines
1.1 KiB
Go
Raw Normal View History

2020-09-09 11:48:46 +02:00
package adverr
import (
2020-09-09 14:06:31 +02:00
"fmt"
2020-09-09 11:48:46 +02:00
"runtime"
"strconv"
"strings"
)
// CallTrace represents a call stack trace similar to Java's stack trace
type CallTrace struct {
frames *runtime.Frames
2020-09-09 14:06:31 +02:00
more bool
2020-09-09 11:48:46 +02:00
}
// Trace returns a new CallTrace starting from this call
// Use skip to skip the first entries in the trace
func Trace(skip int) *CallTrace {
2020-09-09 14:06:31 +02:00
if DisableTrace {
2020-09-09 11:48:46 +02:00
return nil
}
2020-09-09 14:06:31 +02:00
pc := make([]uintptr, CallStackLength+1)
2020-09-09 11:48:46 +02:00
n := runtime.Callers(skip+1, pc)
pc = pc[:n]
2020-09-09 14:06:31 +02:00
fmt.Println(n, CallStackLength)
return &CallTrace{runtime.CallersFrames(pc), n == CallStackLength+1}
2020-09-09 11:48:46 +02:00
}
func (ct *CallTrace) String() string {
if ct == nil {
return ""
}
b := new(strings.Builder)
for frame, ok := ct.frames.Next(); ok; frame, ok = ct.frames.Next() {
b.WriteString("\tat ")
b.WriteString(frame.Function)
b.WriteString(" (")
b.WriteString(frame.File)
b.WriteString(":")
b.WriteString(strconv.Itoa(frame.Line))
b.WriteString(")")
b.WriteString("\n")
}
2020-09-09 14:06:31 +02:00
if ct.more {
b.WriteString("\t ...\n")
}
2020-09-09 11:48:46 +02:00
return b.String()
}