package adverr import ( "runtime" "strconv" "strings" ) // CallStack represents a call stack trace similar to Java's stack trace type CallStack struct { frames *runtime.Frames more bool } // Trace returns a new CallTrace starting from this call // Use skip to skip the first entries in the trace func Trace(skip int) *CallStack { if DisableTrace { return nil } pc := make([]uintptr, CallStackLength+1) n := runtime.Callers(skip+1, pc) pc = pc[:n] return &CallStack{runtime.CallersFrames(pc), n == CallStackLength+1} } func (ct *CallStack) 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") } if ct.more { b.WriteString("\t ...\n") } return b.String() }