1. 25
    1. 4

      I started using slog a few weeks ago. I’m pretty happy with it so far. I am eager to see it become part of the standard library so third party libraries can rely on it.

      1. 1

        Other than slog being (eventually) part of the standard library, do you prefer it to other popular structured logging libraries for Go? Or is it mostly that you want an agreed-upon standard library solution?

        1. 6

          I think the idea is that all logging libs will standardize on slog.Handler as the backend.

        2. 3

          I just want an agreed upon solution, so we don’t have to have boilerplate like

          type Logger interface{
            Printf(string, ...any)
          }
          

          in every third party package that wants to accept a logger.

    2. 3

      Curious how is it different from https://github.com/sirupsen/logrus?

      We have been using it for so many years, and worked well for us in production.

      1. 1

        The implementation discussion calls out logrus as an inspiration. The idea is to make a Go standard so package A can use logrus and package B can use go-kit, and they can both funnel messages into slog and from there to whatever the collector is.

    3. 2

      I think there’s a small typo in the output from the first code sample. The output of the second log line should be this:

      time=2009-11-10T23:00:00.000Z level=ERROR msg="something went wrong" err="file does not exist" file=/tmp/abc.txt
      

      More substantively, there seems to be some magic here.

      log.Error("something went wrong", fakeErr, "file", "/tmp/abc.txt")
      

      The first input is given the key msg, and the error is given the key err, but the last two are explicitly key=value. I’m sure I can get used to the rules here, but what’s the rationale about this? I don’t have a lot of experience with structured logging, but go-kit/log, which I’ve used, seems to be more explicit. My immediate reaction is that I prefer more explicit and less magic inference.

      1. 5

        That’s been a pretty big point of contention. The current signature uses reflection for the key/value pair. https://pkg.go.dev/golang.org/x/exp/slog#Logger.Info

        func (l *Logger) Info(msg string, args ...any)
        

        There’s an additional LogAttr method that may be used if more performance is required: https://pkg.go.dev/golang.org/x/exp/slog#Logger.LogAttrs

        func (l *Logger) LogAttrs(level Level, msg string, attrs ...Attr)
        

        A lot of people would prefer

        func (l *Logger) Info(msg string, attrs ...Attr)
        

        Which would be invoked like this:

        log.Info("something happened", slog.Int("key", 123), slog.String("file", "/tmp/abc.txt"))
        
        1. 1

          Thanks for giving me the background. As my other comments make clear, I am definitely on team explicit. Either way, I’ll look into slog since it’s likely to become a standard choice.

      2. 2

        log.Error has a slot for errors in its signature as a convenience. You can also do log.Log(slog.LevelError, "something went wrong", "err", fakeErr, "file", "/tmp/abc.txt").

        1. 2

          Got it. I’d probably need to write more to be sure, but at first glance I prefer the explicit style.

          Currently, using go-kit/log, I have code that looks like this, and I appreciate how explicit it is:

          level.Error(logger).Log(
          	"file", link.File,
          	"URL", link.URL,
          	"status", link.Status,
          	"error", link.Err,
          )
          
          1. 2

            There’s a proof of concept adaptor so you can keep using the go-kit interface but have it send records out to slog:

            https://github.com/jba/slog/blob/main/gokit/gokit.go

      3. 2

        Thanks for pointing out the typo, fixed!

        Regarding being explicit - I agree with you. But here, I guess for a better DX, error is a required argument only when you call .Error(): https://pkg.go.dev/golang.org/x/exp/slog#Logger.Error

        I guess I prefer this because error key is a standardized field and the function argument itself expecting error only for .Error() is a fair design IMHO. Otherwise, you could also have an inconsistent output format in a large codebase where some code could be using err, instead of error etc.

    4. 1

      I’m not sure if anyone is following this thread anymore, but slog has officially been accepted into the standard library.

      https://github.com/golang/go/issues/56345#issuecomment-1470506816