Skip to content

Commit

Permalink
Callers: Verify behavior for large limits
Browse files Browse the repository at this point in the history
This tests the beahvior of Callers when the limit is larger than 64 (the
value used by the pool by default).
  • Loading branch information
abhinav committed Mar 27, 2020
1 parent 3520ae7 commit d568a1e
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 4 deletions.
2 changes: 1 addition & 1 deletion logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ func (log *Logger) check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry {
}

if addStack {
ce.Entry.Stack = makeStacktrace(pcs)
ce.Entry.Stack = makeStacktrace(pcs, true /* skip zap */)
}

return ce
Expand Down
9 changes: 6 additions & 3 deletions stacktrace.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,24 @@ func takeStacktrace() string {
pcs := newProgramCounters()
defer pcs.Release()

return makeStacktrace(pcs.Callers(1 /* skip */, 0 /* limit */))
return makeStacktrace(
pcs.Callers(1 /* skip */, 0 /* limit */),
true, // skip zap
)
}

func makeStacktrace(pcs []uintptr) string {
func makeStacktrace(pcs []uintptr, skipZapFrames bool) string {
buffer := bufferpool.Get()
defer buffer.Free()

i := 0
skipZapFrames := true // skip all consecutive zap frames at the beginning.
frames := runtime.CallersFrames(pcs)

// Note: On the last iteration, frames.Next() returns false, with a valid
// frame, but we ignore this frame. The last frame is a a runtime frame which
// adds noise, since it's only either runtime.main or runtime.goexit.
for frame, more := frames.Next(); more; frame, more = frames.Next() {
// skip all consecutive zap frames at the beginning.
if skipZapFrames && isZapFrame(frame.Function) {
continue
} else {
Expand Down
32 changes: 32 additions & 0 deletions stacktrace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,35 @@ func BenchmarkTakeStacktrace(b *testing.B) {
takeStacktrace()
}
}

func TestProgramCountersCallersWithLargeLimit(t *testing.T) {
const (
N = 128
testName = "go.uber.org/zap.TestProgramCountersCallersWithLargeLimit"
withStackDepthName = "go.uber.org/zap.withStackDepth"
)

var trace string
withStackDepth(N, func() {
pcs := newProgramCounters().Callers(0, N+2)
trace = makeStacktrace(pcs, false /* don't skip zap */)
})

assert.Contains(t, trace, testName)
for found := 0; found < N; found++ {
i := strings.Index(trace, withStackDepthName)
if i < 0 {
t.Fatalf(`expected %d occurrences of %q, found %d`, N, withStackDepthName, found)
}

trace = trace[i+len(withStackDepthName):]
}
}

func withStackDepth(depth int, f func()) {
if depth > 0 {
withStackDepth(depth-1, f)
} else {
f()
}
}

0 comments on commit d568a1e

Please sign in to comment.