func deepStack(depth int, b *testing.B) stack.CallStack { if depth > 0 { return deepStack(depth-1, b) } b.StartTimer() s := stack.Trace() return s }
// CallerStackHandler returns a Handler that adds a stack trace to the context // with key "stack". The stack trace is formated as a space separated list of // call sites inside matching []'s. The most recent call site is listed first. // Each call site is formatted according to format. See the documentation of // package github.com/go-stack/stack for the list of supported formats. func CallerStackHandler(format string, h Handler) Handler { return FuncHandler(func(r *Record) error { s := stack.Trace().TrimBelow(r.Call).TrimRuntime() if len(s) > 0 { r.Ctx = append(r.Ctx, "stack", fmt.Sprintf(format, s)) } return h.Log(r) }) }
func getTrace(t *testing.T) (stack.CallStack, int) { cs := stack.Trace().TrimRuntime() _, _, line, ok := runtime.Caller(0) line-- if !ok { t.Fatal("runtime.Caller(0) failed") } return cs, line }
// Test that Context.Log has a consistent function stack depth when binding // log.Valuers, regardless of how many times Context.With has been called or // whether Context.Log is called via an interface typed variable or a concrete // typed variable. func TestContextStackDepth(t *testing.T) { t.Parallel() fn := fmt.Sprintf("%n", stack.Caller(0)) var output []interface{} logger := log.Logger(log.LoggerFunc(func(keyvals ...interface{}) error { output = keyvals return nil })) stackValuer := log.Valuer(func() interface{} { for i, c := range stack.Trace() { if fmt.Sprintf("%n", c) == fn { return i } } t.Fatal("Test function not found in stack trace.") return nil }) concrete := log.NewContext(logger).With("stack", stackValuer) var iface log.Logger = concrete // Call through interface to get baseline. iface.Log("k", "v") want := output[1].(int) for len(output) < 10 { concrete.Log("k", "v") if have := output[1]; have != want { t.Errorf("%d Withs: have %v, want %v", len(output)/2-1, have, want) } iface.Log("k", "v") if have := output[1]; have != want { t.Errorf("%d Withs: have %v, want %v", len(output)/2-1, have, want) } wrapped := log.NewContext(concrete) wrapped.Log("k", "v") if have := output[1]; have != want { t.Errorf("%d Withs: have %v, want %v", len(output)/2-1, have, want) } concrete = concrete.With("k", "v") iface = concrete } }
func Stack(skip int) string { call := stack.Caller(skip) s := stack.Trace().TrimBelow(call).TrimRuntime() return s.String() }
func BenchmarkTraceAndVFmt(b *testing.B) { for i := 0; i < b.N; i++ { fmt.Fprint(ioutil.Discard, stack.Trace()) } }
func BenchmarkTrace(b *testing.B) { for i := 0; i < b.N; i++ { stack.Trace() } }
func TestTrimRuntime(t *testing.T) { trace := stack.Trace().TrimRuntime() if got, want := len(trace), 1; got != want { t.Errorf("got len(trace) == %v, want %v, goroot: %q, trace: %#v", got, want, runtime.GOROOT(), trace) } }
func trimBelow() stack.CallStack { call := stack.Caller(1) trace := stack.Trace() return trace.TrimBelow(call) }
func trimAbove() stack.CallStack { call := stack.Caller(1) trace := stack.Trace() return trace.TrimAbove(call) }