-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Honor CallerSkip when taking stack traces & add the StackSkip field #843
Honor CallerSkip when taking stack traces & add the StackSkip field #843
Conversation
* UseCallerSkipForStacktrace configures the Logger to honor CallerSkip when taking stacktraces. * StackSkip is similar to Stack but allows skipping frames from the top of the stack Fixes uber-go#512, fixes uber-go#727
Codecov Report
@@ Coverage Diff @@
## master #843 +/- ##
==========================================
+ Coverage 98.33% 98.35% +0.02%
==========================================
Files 43 43
Lines 2349 2378 +29
==========================================
+ Hits 2310 2339 +29
Misses 32 32
Partials 7 7
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking this on @segevfiner
After reviewing, I have a couple of questions:
- Do we need
StackSkip
: It's is not used or needed for the logger to skip stack frames based on caller skip, so doesn't seem too related to the change. - I think leaving the stacktrace pruning as-is is best for backwards compatibility
I think using an option is the right thing for backwards compatibility, although in this case, I think it may be more of a bug that the stacktrace attached skips zap stackframes, but doesn't take callerSkip
into apply.
We should also get @abhinav's opinion on this -- would you prefer to leave the option (which likely means most users won't find this/enable this) which helps maintain compatibility exactly?
We don't have too, it's just for completeness. Zap takes a stack trace, and the user can take a stack using the
That's why I kept it for the time being and why it's being a flag. Though I wonder if that flag is on should we also do zap stackframe pruning or rely on |
4169790
to
c27b7e4
Compare
I discussed whether we should default
Given that, we agreed on:
Would you be able to update your change to match the above behaviour @segevfiner? Thanks! |
@prashantv I can. I will just need to find some time for it. Effectively I'll be removing the option and moving to always use the new behavior. The only problem part is the zap stack frame trimming which I kept to preserve the old behavior when the option is false, which will then only be used for the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Besides minor stylistic comments, this is a good direction.
As @prashantv suggested, I'm in favor of making this the default behavior. We can add the flag later as needed.
a2a5f11
to
20dc3e4
Compare
Also remove the zap frame skipping logic in favour of zap setting the skip correctly when taking the stack trace.
20dc3e4
to
80d2017
Compare
Made the requested change. |
stacktrace.go
Outdated
buffer := bufferpool.Get() | ||
defer buffer.Free() | ||
programCounters := _stacktracePool.Get().(*programCounters) | ||
defer _stacktracePool.Put(programCounters) | ||
|
||
var numFrames int | ||
for { | ||
// Skip the call to runtime.Counters and takeStacktrace so that the | ||
// Skip the call to runtime.Callers and takeStacktrace so that the | ||
// program counters start at the caller of takeStacktrace. | ||
numFrames = runtime.Callers(2, programCounters.pcs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we implement skip
manually below, can't we just add it here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leftover from still having skip zap frames.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great! I have some minor fix-ups for some of the tests, and it looks like TestStackSkipField and TestStackSkipfieldWithSkip are unintentionally the same.
assertCanBeReused(t, f) | ||
} | ||
|
||
func TestStackSkipFieldWithSkip(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There doesn't appear to be any difference between this and TestStackSkipField. Did you mean to use zero for TestStackSkipField?
stacktrace_ext_test.go
Outdated
require.Contains(t, out.String(), "TestStacktraceWithoutCallerSkip.", "Should not skip too much") | ||
require.Contains(t, out.String(), "TestStacktraceWithoutCallerSkip", "Should not skip too much") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we pass the first check, we'll always also pass the second check. We can probably just drop the second.
require.Contains(t, out.String(), "TestStacktraceWithoutCallerSkip.", "Should not skip too much") | |
require.Contains(t, out.String(), "TestStacktraceWithoutCallerSkip", "Should not skip too much") | |
require.Contains(t, out.String(), "TestStacktraceWithoutCallerSkip.", "Should not skip too much") |
stacktrace_test.go
Outdated
func TestTakeStacktraceWithSkip(t *testing.T) { | ||
trace := takeStacktrace(1) | ||
lines := strings.Split(trace, "\n") | ||
require.True(t, len(lines) > 0, "Expected stacktrace to have at least one frame.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: Can use NotEmpty.
require.True(t, len(lines) > 0, "Expected stacktrace to have at least one frame.") | |
require.NotEmpty(t, lines, "Expected stacktrace to have at least one frame.") |
stacktrace_test.go
Outdated
t, | ||
lines[0], | ||
"testing.", | ||
"Expected stacktrace to start with the test runner (skipping our own frame) %s.", lines[0], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: Testify will include the lines[0]
in the output so we don't need to.
"Expected stacktrace to start with the test runner (skipping our own frame) %s.", lines[0], | |
"Expected stacktrace to start with the test runner (skipping our own frame).", |
stacktrace_test.go
Outdated
trace = takeStacktrace(2) | ||
}() | ||
lines := strings.Split(trace, "\n") | ||
require.True(t, len(lines) > 0, "Expected stacktrace to have at least one frame.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
require.True(t, len(lines) > 0, "Expected stacktrace to have at least one frame.") | |
require.NotEmpty(t, lines, "Expected stacktrace to have at least one frame.") |
stacktrace_test.go
Outdated
t, | ||
lines[0], | ||
"testing.", | ||
"Expected stacktrace to start with the test function (skipping the test function) %s.", lines[0], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Expected stacktrace to start with the test function (skipping the test function) %s.", lines[0], | |
"Expected stacktrace to start with the test function (skipping the test function.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
The change looks good! Can we update the title / summary to reflect the changes made during code review (we now always respect caller skip when taking stack traces as part of an entry) |
@prashantv Updated. |
…ber-go#843) * Honor `CallerSkip` when taking a stack trace. Both the caller and stack trace will now point to the same frame. * Add `StackSkip` which is similar to `Stack` but allows skipping frames from the top of the stack. This removes the internal behavior of skipping zap specific stack frames when taking a stack trace, and instead relies on the same behavior used to calculate the number of frames to skip for getting the caller to also skip frames in the stack trace. Fixes uber-go#512, fixes uber-go#727
CallerSkip
when taking a stack trace. Both the caller and stack trace will now point to the same frame.StackSkip
which is similar toStack
but allows skipping frames from the top of the stack.This removes the internal behavior of skipping zap specific stack frames when taking a stack trace, and instead relies on the same behavior used to calculate the number of frames to skip for getting the caller to also skip frames in the stack trace.
Fixes #512, fixes #727