-
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
feat(zapslog): implement stack trace handling #1339
Conversation
stacktrace.go
Outdated
@@ -125,6 +125,12 @@ func (st *stacktrace) Next() (_ runtime.Frame, more bool) { | |||
return st.frames.Next() | |||
} | |||
|
|||
// TakeStacktrace returns the stack trace, | |||
// and skips the provided number of frames. | |||
func TakeStacktrace(skip int) string { |
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.
Should we deprecate
this and add a comment that it's just a temporary export? Although we might want to implement this first because /exp/slog
relies on zap 1.24.0 :
Line 7 in fd37f1f
go.uber.org/zap v1.24.0 |
to make it work i need to modify the go.mod:
module go.uber.org/zap/exp
go 1.19
require (
github.com/stretchr/testify v1.8.1
go.uber.org/zap v1.24.0
golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.10.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
replace go.uber.org/zap => ../
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.
I don't like the idea of exporting this functionality from the main Zap package even as a temporary unsupported thing.
Instead, I've moved the relevant bits into an internal package in #1341.
That makes it easy to use them 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.
Thanks for this i agree on this approach too
exp/zapslog/slog_pre_go121.go
Outdated
Time: record.Time, | ||
Message: record.Message, | ||
LoggerName: h.name, | ||
// TODO: do we need to set the following fields? |
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.
Stack
was not required for the implementation
3b30b92
to
964a1cc
Compare
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 doing this, and thanks for waiting for the review. It's a bit busy these days.
I'll try to get #1341 landed soon to capture the stack traces without exporting them from the main Zap package.
And yeah, exp/ will need a replace
directive. We'll have to be careful about updating exp/ to the latest Zap release when we tag it.
exp/zapslog/slog_go121.go
Outdated
@@ -157,6 +144,10 @@ func (h *Handler) Handle(ctx context.Context, record slog.Record) error { | |||
} | |||
} | |||
|
|||
if h.addStack.Enabled(zapLevel) { | |||
ce.Stack = zap.TakeStacktrace(4 + h.callerSkip) |
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.
I would add a comment here for each of the 4 skips we're adding, e.g. skip Handle, slog.LogAttr, [..]
, etc.
I suspect this might not be as straightforward.
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.
Sure I'll add revelant comments
stacktrace.go
Outdated
@@ -125,6 +125,12 @@ func (st *stacktrace) Next() (_ runtime.Frame, more bool) { | |||
return st.frames.Next() | |||
} | |||
|
|||
// TakeStacktrace returns the stack trace, | |||
// and skips the provided number of frames. | |||
func TakeStacktrace(skip int) string { |
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.
I don't like the idea of exporting this functionality from the main Zap package even as a temporary unsupported thing.
Instead, I've moved the relevant bits into an internal package in #1341.
That makes it easy to use them here.
I've pushed some minor fixups to your branch. Please be sure not to lose them if you |
We don't need AddCaller and WithCaller both. WithCaller was added because AddCaller doesn't take a parameter.
c639ac6
to
3be64f5
Compare
3be64f5
to
b66a3d3
Compare
@abhinav I rebased and applied all the comments |
Codecov Report
@@ Coverage Diff @@
## master #1339 +/- ##
==========================================
- Coverage 97.95% 97.72% -0.23%
==========================================
Files 51 52 +1
Lines 3369 3392 +23
==========================================
+ Hits 3300 3315 +15
- Misses 59 67 +8
Partials 10 10
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
@abhinav should i add tests for the options or we add them in another PR? I'm happy to write a follow up one if needed |
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.
Hey @zekth, apologies; I haven't forgotten about this, but I've had (and continue to have) a busy few days. I've taken a pass; this mostly looks good to go with minor comments. I'll address a few myself in a few minutes.
Tagging other Zap maintainers as well. CC @sywhang @mway @prashantv
(Context: This PR turns HandlerOptions into functional options per prior discussion, and adds support for stack traces. Stack traces are captured for Error and above -- same as Zap's production logger.)
RE: tests: There's no need to backfill tests for existing options at this time--tests for the new option you're adding for stack traces should be sufficient. We do intend to fill in the rest of the tests before moving this to the main Zap package, though, but that's out of scope for this PR.
// Skipping 3: | ||
// zapslog/handler log/slog.(*Logger).log | ||
// slog/logger log/slog.(*Logger).log | ||
// slog/logger log/slog.(*Logger).<level> | ||
ce.Stack = stacktrace.Take(3 + h.callerSkip) |
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 adding this. Much more obvious what's going on now.
exp/zapslog/options.go
Outdated
// AddStacktrace configures the Logger to record a stack trace for all messages at | ||
// or above a given level. | ||
func AddStacktrace(lvl zapcore.LevelEnabler) Option { |
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.
Just thinking out loud (would love your opinion on this, @zekth):
I wonder if this should be a slog Level instead. Or a new zapslog.LevelEnabler interface based on slog.Level.
type LevelEnabler interface{ Enabled(context.Context, Level) bool }
The reasoning is this: the result of zapslog.NewHandler is a slog Handler. It talks in the language of slog.
And update documentation.
Changes AddStacktrace to use a slog.Level instead of a Zap Level, and renames it to AddStacktraceAt. This leaves room for a LevelEnabler (as suggested in the PR) to be specified with an AddStacktrace in the future.
On LevelEnabler and whether this should use a Zap level or slog level. |
We avoid use of assert.New and require.New in our tests.
Now that zaplevel isn't used to determine if we need to capture the stack trace, it can be inlined back into the entry construction.
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 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.
fix: #1329
As discussed in the issue, replacing the
HandlersOptions
with functional options, i also renamedaddSource
toaddCaller
to properly match thezap
semantic.