Live data from Hacker News

Logging in Go with Slog: A Practitioner's Guide

dash0.com

31–40 of 59 posts

Re: Logging in Go with Slog: A Practitioner's Guide

#31
post #22

Earlier quoted context omitted.

That seems to work as expected? The output of data is handled by the handler. Such behaviour is clearly outlined in the documentation by the JSONHandler. I wouldn't expect a JSONHandler to use Stringer. I'd expect it to use the existing JSON interfaces, which it does. I'd expect the Text handler to use TextMarshaller. Which it does. Or Stringer, which it does implicitly via fmt.Sprintf.

My problem with that is that it makes it impossible to use slog logger safely without knowing what handler is being used. Which kind of defeats the purpose of defining the common structured logging interface.

[deleted]

Re: Logging in Go with Slog: A Practitioner's Guide

#32
post #30

It's fine for application logging but I have two gripes with slog: 1) If you're writing a library that can be used by many different applications and want to emit logs, you'll still need to write a generic log interface with adapters for slog, zap, charmlog, etc. That the golang team refuses to bless a single interface for everyone to settle on both makes sense given their ideological standpoint on shipping interface…

> That the golang team refuses to bless a single interface for everyone to settle on Uh... https://pkg.go.dev/golang.org/x/exp/slog#Handler If zap, charmlog, etc. don't provide conformance to the interface, that's not really on the Go team. It wouldn't be that hard to write your own adapter around your unidiomatic logger of choice if you're really stuck, though. This isn't an actual problem unless you think someone e…

That's close, but not what I meant — that's specific to this package, and is the interface for processing log records produced by a slog.Logger. What I mean is that there should be a single interface for Logging that is implemented by slog.Logger, uber/zap.Logger, etc. that library authors can use without needing to reinvent the wheel every time.

For an example from one of my own libraries, see

https://github.com/peterldowns/pgmigrate/blob/d3ecf8e4e8af87...

Re: Logging in Go with Slog: A Practitioner's Guide

#33
post #22

Earlier quoted context omitted.

That seems to work as expected? The output of data is handled by the handler. Such behaviour is clearly outlined in the documentation by the JSONHandler. I wouldn't expect a JSONHandler to use Stringer. I'd expect it to use the existing JSON interfaces, which it does. I'd expect the Text handler to use TextMarshaller. Which it does. Or Stringer, which it does implicitly via fmt.Sprintf.

My problem with that is that it makes it impossible to use slog logger safely without knowing what handler is being used. Which kind of defeats the purpose of defining the common structured logging interface.

> Which kind of defeats the purpose of defining the common structured logging interface.

Does it, though? Why would the log producer care about how the log entires are formatted? Only the log consumer cares about that.

Re: Logging in Go with Slog: A Practitioner's Guide

#34
post #24

It's fine for application logging but I have two gripes with slog: 1) If you're writing a library that can be used by many different applications and want to emit logs, you'll still need to write a generic log interface with adapters for slog, zap, charmlog, etc. That the golang team refuses to bless a single interface for everyone to settle on both makes sense given their ideological standpoint on shipping interface…

1) The idea is that your library should accept the slog logger and use it. The caller would create a logger with a handler that defines how log messages are handled. But there are problems with supported types; see my other comments. 2) It is improved in 1.25. See https://github.com/golang/go/issues/59928 and https://pkg.go.dev/testing#T.Output . Now it is possible to update slogt to provide correct callsite – the st…

1) Right, but this is complicated and annoying. Imagine a world where you could just pass your existing logger in, because my library references an interface like `stdlib/logging.GenericLoggerInterface` and slog, zap, zerolog, etc. all implement that! Would be nice!

2) TIL about `T.Output`, thank you, that's great to know about. Still annoying and would be nice if the slog package showed an example of logging from tests with correct callsites. Golang gets so many things right about testing, so the fact that logging in tests is difficult really stands out and bothers me.

Re: Logging in Go with Slog: A Practitioner's Guide

#35
post #30

Earlier quoted context omitted.

> That the golang team refuses to bless a single interface for everyone to settle on Uh... https://pkg.go.dev/golang.org/x/exp/slog#Handler If zap, charmlog, etc. don't provide conformance to the interface, that's not really on the Go team. It wouldn't be that hard to write your own adapter around your unidiomatic logger of choice if you're really stuck, though. This isn't an actual problem unless you think someone e…

That's close, but not what I meant — that's specific to this package, and is the interface for processing log records produced by a slog.Logger. What I mean is that there should be a single interface for Logging that is implemented by slog.Logger, uber/zap.Logger, etc. that library authors can use without needing to reinvent the wheel every time. For an example from one of my own libraries, see https://github.com/pet…

> What I mean is that there should be a single interface for Logging that is implemented by slog.Logger, uber/zap.Logger, etc.

There is: https://pkg.go.dev/golang.org/x/exp/slog#Handler

If, say, zap was conformant, you'd slog.New(zap.NewHandler()) or whatever and away you go. It seems the only problem here is that the logging packages you want to use are not following the blessed, idiomatic path.

> For an example from one of my own libraries

There are a lot of problem with that approach at scale. That might not matter for your pet projects, but slog also has to serve those who are pushing computers to their limits. Your idea didn't escape anyone.

Re: Logging in Go with Slog: A Practitioner's Guide

#36
post #35

Earlier quoted context omitted.

That's close, but not what I meant — that's specific to this package, and is the interface for processing log records produced by a slog.Logger. What I mean is that there should be a single interface for Logging that is implemented by slog.Logger, uber/zap.Logger, etc. that library authors can use without needing to reinvent the wheel every time. For an example from one of my own libraries, see https://github.com/pet…

> What I mean is that there should be a single interface for Logging that is implemented by slog.Logger, uber/zap.Logger, etc. There is: https://pkg.go.dev/golang.org/x/exp/slog#Handler If, say, zap was conformant, you'd slog.New(zap.NewHandler()) or whatever and away you go. It seems the only problem here is that the logging packages you want to use are not following the blessed, idiomatic path. > For an example fro…

I know it didn't escape anyone; I'm explaining the downside to the choices made by the stdlib authors, from my perspective. When performance is a concern, people pick uber/zap.Logger or zerolog. When performance isn't a huge concern, slog is overly complicated and annoying. I believe you understand my complaint.

Re: Logging in Go with Slog: A Practitioner's Guide

#37
post #33
post #22

Earlier quoted context omitted.

My problem with that is that it makes it impossible to use slog logger safely without knowing what handler is being used. Which kind of defeats the purpose of defining the common structured logging interface.

> Which kind of defeats the purpose of defining the common structured logging interface. Does it, though? Why would the log producer care about how the log entires are formatted? Only the log consumer cares about that.

[flagged]

Re: Logging in Go with Slog: A Practitioner's Guide

#38
Cool article.

I really like structured logs and am pleased the Go team saw the benefits of bringing it into the standard library.

However, I feel like errors should be able to hold slog attributes. It makes for some very useful and easy error logging, especially when the logging takes place far up the execution chain from where the error happened.

This is easily possible with a custom error type and some log functions. I have published on GitHub my small and crude implementation that I use in a few hobby projects, MIT licensed, if anyone is interested. https://github.com/sveinnthorarins/sterlo

Re: Logging in Go with Slog: A Practitioner's Guide

#39
post #35

Earlier quoted context omitted.

> What I mean is that there should be a single interface for Logging that is implemented by slog.Logger, uber/zap.Logger, etc. There is: https://pkg.go.dev/golang.org/x/exp/slog#Handler If, say, zap was conformant, you'd slog.New(zap.NewHandler()) or whatever and away you go. It seems the only problem here is that the logging packages you want to use are not following the blessed, idiomatic path. > For an example fro…

I know it didn't escape anyone; I'm explaining the downside to the choices made by the stdlib authors, from my perspective. When performance is a concern, people pick uber/zap.Logger or zerolog. When performance isn't a huge concern, slog is overly complicated and annoying. I believe you understand my complaint.

> I believe you understand my complaint.

I don't, really. If performance is of utmost concern, you're not going to accept the overhead of passing the logger through an interface anyway, so that's moot. A library concerned about performance as a top priority has to pick one and only one.

But if a library has decided that flexibility is more important than raw efficiency, then the interface is already defined.

    zaplogger.Info("Calling third-party library")
    thirdparty.Call(slog.New(zaplogger)) // Logs whatever the package logs to zaplogger
    zaplogger.Info("Called third-party library")
The only 'problem' I can see is if `zaplogger` hasn't implemented the interface. But there isn't much the Go team can do about implementations not playing nicely.

Re: Logging in Go with Slog: A Practitioner's Guide

#40
post #25

> The key decision is thus between two patterns: using a global logger or using dependency injection. The former is extremely convenient but adds a hidden dependency that’s hard to test, while the latter is more verbose but makes dependencies explicit, resulting in highly testable and flexible code. Curious how different people handle this. I personally pretty much always pass a logger into function, classes, structs…

We pass logs in contexts.
Post reply on HN