-
Notifications
You must be signed in to change notification settings - Fork 67
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
slog: Support structured logging #17
base: master
Are you sure you want to change the base?
Conversation
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.
Very nice! LGTM, just a couple of nits and/or suggestions.
Really excited to get this in so we can have structured logs in lnd
.
Which sets the new minimum golang version required for compiling the package to go 1.21 which is when the standard library `log/slog` package was introduced.
So that it does not clash with the standard lib's slog package.
Reuse some of the slog.Level types and add a few of our own. Also, move level logic to its own file for readability.
And let subLog implement the methods by calling its existing methods. Note that subLog will not produce structured logs as of this commit. In future, it can be updated to use an slog.Logger and this package can implement a default slog.Handler.
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 @guggero 📁
Note to reviewers: Im going to look into writing a Default Handler that can be passed to the NewSLog() constructor that will result in the output looking identical to the existing sublogger output. If this is done, then we can actually just completely remove the |
Note: I have updated the PR to include a default Handler that can be used with the new NewSlogger method :) |
Update the buffer pool to use a concrete type and steel some other updates from the buffer pool used by std lib. Also adds a few useful helpers that we will use later on and also factors out the timestamp writing part from formatHeader since we will use that again later.
Since we will use it later no with a different skip depth.
7a9bd83
to
c3830ec
Compare
Which is a valid Handler that can be used with the NewSloggger call.
I have also added a test now |
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.
Great stuff! Super cool that we can get all of those features with zero additional dependencies 💯
// | ||
// This is part of the Logger interface implementation. | ||
func (l *subLog) TraceS(_ context.Context, msg string, attrs ...any) { | ||
l.Tracef(msg, attrs...) |
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.
Do we need to process the attrs
first? Or is the assumption that msg
would never contain formatting directives? Then perhaps we should call into l.Trace()
instead.
Example of what I mean:
bar := "bar"
subLog.TraceS(ctx, "incorrectly used directive: %v", "foo", bar)
What I think would be printed:
incorrectly used directive: foo%!(EXTRA string=bar)
What the user would expect to be printed:
incorrectly used directive: foo=bar
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.
cool yeah agreed
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.
ah - the thing is thought that for this implementation, under the hood there is not actually structured logging going on. So the output we get will not look like "key=value" etc. So I used the *f
methods just so that we are passing the msg
and attr
to some underlying impl. the non f
methods only take ...attr
so the message would not be used.
So this was just to somewhat complete this implementation. In reality if callers want structured logging, they should use the new slog implementation. In the LL fork PR, I completely remove this impl anyways. So I think instead of trying to get this to work as if it is using slog underneath, let's just add a warning to the impl saying it works like the *f
methods.
Taking a step back: i think we arent gonna get this into this repo anyways and so we will carry on with the forked version which removes this impl anyways
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.
EDIT given latest updates to the convo: perhaps I should just look into a best effort way of converting the given attributes to k=v pairs and writing those to the writer
d.appendAttr(buf, attr) | ||
} | ||
|
||
// Append slog attributes |
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.
nit: missing full stop.
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.
Pending Oli's comments, otherwise LGTM🙏
Ok yall: thanks so much for review here! I think we are gonna go with the forking path here as I dont think the maintainer(s) of the repo is/are active. So let's move discussion & final review there: lightninglabs#1 EDIT: nevermind... if we fork this then we'd also need to fork every other btcsuite PR that we use that imports the logger.... |
cc @davecgh |
@Roasbeef What's up? I guess maybe perms? I really no longer have anything to do with maintaining btc things. A couple of things I noticed on a quick review though is:
|
Aside from the two aforementioned things, and some nits like missing copyright headers, the changes otherwise look fine. As I said though, I no longer maintain anything btc, so I'll defer to @Roasbeef to make merge decisions. |
The reason that go1.21 was chosen is cause
it is off by default - but if we are worried about this, i can update the PR to just allow the user to pass in various
Ok cool |
Aye, I understand the reasoning. The code was changed over to define Regardless of the rationale though, the effect is that anything that uses it will necessarily be hoisted forward thereby forcing everything that uses those things to also be hoisted forwards all the way down the dependency stack. For example, take Even something relatively simple like Without looking super closely, I imagine it would be possible to make this compatible with Go 1.17 by implementing the relevant |
But this is only the case if they want to update to the latest version right? And they would only want to update to the latest version if they want the new features which in this case is The only other reason they'd want to update their btclog dep is if there is some bug found in the old code & they want to update to include just that fix - but for that, we can just maintain a branch that only includes the old implementation & backfills the fix. That way they can point to that branch. It just seems like we should be able to move logging forward and take advantage of new features that go provides us in terms of logging so that those users that want to take advantage of newer features can do so
Meaning just update the interface but have the implementation be defined elsewhere (ie not in this repo)? This would work except for the tricky situation with the |
I think we might be able to get away with using the old version of the package: https://pkg.go.dev/golang.org/x/exp/slog. It doesn't look to use as many recent language features. |
This PR does a few things:
Logger
interface with new structured logging messages (DebugS
,InfoS
etc)log/slog
implementation of theLogger
that uses proper structured logging.Details
slog.Handlers
(which underneath could be a json formatter, a logfmt formatter or any anything else like a charm HandlerUsage
The idea is that the
msg
passed to anS
method should be a constant. Theattr...
params are then used for key-value pairs.Each new method also takes a
context.Context
. TheWithCtx
helper can be used to attach any key-value pairs to acontext and then when the logger is called, the pairs will be extracted from the context and added as attributes in the log.
For example: