-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
log/slog: ReplaceAttr gets Source struct instead of file:line #59280
Comments
This feels like the right insight to me - if interested, users can provide some function At the cost of changing slog.HandlerOptions{
AddSource: true,
AddSourceFunc: ..., // defaults to file:line behavior
}
I think this is probably not a huge deal, but changing (*: A |
Instead how about if the |
I agree with @ianthehat - exposing a PC is going to be error prone, but it would be possible to expose instead a
and make that the attribute value. The name Source matches SourceKey. |
We already have |
The added methods of a |
Ever since I read about how PGO uses line offsets within functions to help improve stability of its data across refactorings I've been wondering if caller information in logs might be better reported the same way. To be honest, despite maintaining github.com/go-stack/stack and contributing caller implementations to a couple of logging packages, I haven't been using that feature in logs for the last several years. The reasons are:
Logging a function name and line offset could be both less prone to version skew and possibly more informative (assuming function names have more value than file names). Can we arrange it so that someone could choose to implement something like that? Here's a proof-of-concept: https://go.dev/play/p/7YfnTGA6jRP
|
This proposal has been added to the active column of the proposals project |
@ChrisHines I have sometimes included the runtime
With the |
@StevenACoffman that's another good idea. My point, more simply stated, is don't limit the information artificially. Give us all the data from the
|
I can imagine if I were writing an error logging service like Sentry or Honeycomb, that I would like to make it so that when you call logger.Error it would take a stack trace and ship that off to be recorded for inspection by developers later. |
If we define our own type, we have control over how it marshals. Using runtime.Frame does not give us that control. I'm also not entirely sure that runtime.Frame is really the right API in the runtime, and I'm not sure we should be using it in new APIs. |
Note also that we can add to Source over time. @ChrisHines, what information would you want to add beyond Func, File, Line? |
Unknown. I would possibly want anything the runtime can provide. If the runtime provides more, I might want it. As I've said a few times in the discussion, don't artificially hide information, let it all pass through so we can use it however we want. If I can read the Going way back to when |
I would vote for using the a separate |
If the runtime ever moved to some newer, more efficient API, then we'd be stuck. The Frame exposes things like runtime.Func, which I'd really rather not appear in the slog API. If new important things appear in runtime.Frame, we can make them appear in slog.Source as well. |
I understand the concern. Note also, however, that I made use of It would be nice if we could have some source location ur-value that we believe Go will support for the foreseeable future. If that is not a If we don't have one then it seems we must decouple collecting source location data from the |
@ChrisHines, the current issue is limited to what the built-in handlers pass to |
edit: modified TextHandler to return to source=file:line Here is my proposal: Add
There are no exported methods on The default handler continues to output source locations as "file:line". If
and JSONHandler's output would look like
If
LIkely questions:
|
I think "gets |
I forgot to mention that |
Based on the discussion above, this proposal seems like a likely accept. |
OK. Then I am confused why we |
The slog API has two distinct parts. The majority of users will only use The relatively few handler writers will need to deal with To answer the obvious question, yes, we did think about having two packages. But we decided the extra ceremony wasn't worth it. |
I agree with the general premise of multiple classes of It seems to me that the |
No change in consensus, so accepted. 🎉 |
Change https://go.dev/cl/486376 mentions this issue: |
I am disappointed that this was accepted without any reply to my last comment. Maybe it wasn't fully clear in that post, but I would hope from the discussion context it was clear that I was advocating for giving access to the |
Sorry about that, Chris. I did take your point, but ultimately we thought it was better to keep the split as we have it, with pcs and handlers together on the advanced side. |
OK. I wish I was more persuaded, but so be it, I guess. Thanks for the quick reply. |
Add a struct called Source that holds the function, file and line of a location in the program's source code. When HandleOptions.AddSource is true, the ReplaceAttr function will get an Attr whose key is SourceKey and whose value is a *Source. We use *Source instead of Source to save an allocation. The pointer and the value each cause one allocation up front: the pointer when it is created, and the value when it is assigned to the `any` field of a slog.Value (handle.go:283). If a ReplaceAttr function wanted to modify a Source value, it would have to create a new slog.Value to return, causing a second allocation, but the function can modify a *Source in place. TextHandler displays a Source as "file:line". JSONHandler displays a Source as a group of its non-zero fields. This replaces the previous design, where source location was always a string with the format "file:line". The new design gives users more control over how to output and consume source locations. Fixes golang#59280. Change-Id: I84475abd5ed83fc354b50e34325c7b246cf327c7 Reviewed-on: https://go-review.googlesource.com/c/go/+/486376 TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Jonathan Amsterdam <jba@google.com> Reviewed-by: Alan Donovan <adonovan@google.com>
Add a struct called Source that holds the function, file and line of a location in the program's source code. When HandleOptions.AddSource is true, the ReplaceAttr function will get an Attr whose key is SourceKey and whose value is a *Source. We use *Source instead of Source to save an allocation. The pointer and the value each cause one allocation up front: the pointer when it is created, and the value when it is assigned to the `any` field of a slog.Value (handle.go:283). If a ReplaceAttr function wanted to modify a Source value, it would have to create a new slog.Value to return, causing a second allocation, but the function can modify a *Source in place. TextHandler displays a Source as "file:line". JSONHandler displays a Source as a group of its non-zero fields. This replaces the previous design, where source location was always a string with the format "file:line". The new design gives users more control over how to output and consume source locations. Fixes golang#59280. Change-Id: I84475abd5ed83fc354b50e34325c7b246cf327c7 Reviewed-on: https://go-review.googlesource.com/c/go/+/486376 TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Jonathan Amsterdam <jba@google.com> Reviewed-by: Alan Donovan <adonovan@google.com>
If
HandlerOptions.AddSource
is set to true, the built-in handlers behave as if the attribute with keySourceKey
and string value "file:line" were present. When aReplaceAttr
function is also provided, it is passed that exact attribute, just as with the other built-in attributes.But this is a missed opportunity to make it easy for users to customize the output of the source location. ("Easy" here meaning a couple of lines of code, compared to writing an entire new Handler.)
Instead, I propose that When
AddSource
is true,ReplaceAttr
is passed anAttr
withSourceKey
and the Record's PC field. It could then do whatever it wished, like including the function name in the returned Attr. If it returned the Attr unchanged, the handler would proceed with the default "file:line" output.Downsides:
Without this change, only Handler writers were exposed to the PC field of the Record. Working with pcs is an advanced topic, and perhaps the everyday users of
slog
should not be asked to deal with it.This is a special case for
ReplaceAttr
. In particular, this is the only time the built-in handlers would make a decision based on its return value (except for eliding empty Attrs).See also #56345.
The text was updated successfully, but these errors were encountered: