Live data from Hacker News

Structured logging with slog

go.dev

61–70 of 174 posts

Re: Structured logging with slog

#61
post #3

With this another most requested feature is covered by Go. This leaves error handling, enum type which are often asked by users but are not actively being worked on for now.

The lack of Error Handling in Go is a feature, not a bug. See here: https://go.dev/doc/faq#exceptions . I think I'd be disappointed if Try/Catch ever made their way into the language.

Yeah I have to agree that the Go-style error handling does actually lead to better code. At least when I write it. It makes me think through how I am going to handle error states rather than chucking it in try/except in Python and hoping nothing breaks lol.

Re: Structured logging with slog

#62
post #8

Admittedly I'm not a huge fan of having: slog.Info("hello, world", "user", os.Getenv("USER")) It's a little magical that "user" is a key. So what if you have multiple key-value pairs? Arguably it most likely going to be obvious which is the keys, but having every other value be a key and the rest values seems a little clumsy. I really like Pythons approach where you can have user="value" it makes things a bit more cl…

Rust's slog ( https://docs.rs/slog/ ) does:

  use slog::info;
  ...
  info!("hello, world"; "user" => std::env::var("USER"));

Re: Structured logging with slog

#63
post #8

Admittedly I'm not a huge fan of having: slog.Info("hello, world", "user", os.Getenv("USER")) It's a little magical that "user" is a key. So what if you have multiple key-value pairs? Arguably it most likely going to be obvious which is the keys, but having every other value be a key and the rest values seems a little clumsy. I really like Pythons approach where you can have user="value" it makes things a bit more cl…

> It's a little magical that "user" is a key. So what if you have multiple key-value pairs? You... add them afterwards? It's really just a plist ( https://www.gnu.org/software/emacs/manual/html_node/elisp/Pr... ), that's hardly novel. The method takes any number of parameters and pairs them up as key, value. Or if you really hate yourself, you use LogAttrs with explicitly constructed Attr objects. > I really like Pyt…

It sure has maps though... logrus famously uses `logrus.Fields{"key": "value"}`

Re: Structured logging with slog

#64
post #3

With this another most requested feature is covered by Go. This leaves error handling, enum type which are often asked by users but are not actively being worked on for now.

An iterator type is being actively worked on now. After that presumably the missing data types in the standard library will be filled out (set, deque, a usable heap, whatever other algorithms). After that, who knows. Maybe native bigints? I don’t really see the enum thing happened. Is lack of enums a real problem? Theoretically, it would be convenient, but I can’t say that I see bugs caused by its lack.

Enums with associated values are a very basic data modeling primitive. Writing code without them is like doing arithmetic with only the multiplication sign, not the plus sign.

Re: Structured logging with slog

#65
post #63

Earlier quoted context omitted.

> It's a little magical that "user" is a key. So what if you have multiple key-value pairs? You... add them afterwards? It's really just a plist ( https://www.gnu.org/software/emacs/manual/html_node/elisp/Pr... ), that's hardly novel. The method takes any number of parameters and pairs them up as key, value. Or if you really hate yourself, you use LogAttrs with explicitly constructed Attr objects. > I really like Pyt…

It sure has maps though... logrus famously uses `logrus.Fields{"key": "value"}`

And logrus is one of the slowest loggers by far, in part because of its heavy map usage.

Re: Structured logging with slog

#66
I'm really glad they've introduced this, I just wish it also had the traditional formatting methods, eg Infof, Debugf, Errorf, etc, for backwards compatibility.

I've got a few packages that accept a basic logger interface, eg:

  type debugLogger interface {
      Debugf(format string, args ...any)
  }

  type MyThing struct {
    logger debugLogger
  }

  func New(logger debugLogger) *MyThing {
    return &MyThing{logger}
  }
I'd love to switch to slog but I'll have to v2 these packages now.

Re: Structured logging with slog

#67
post #38
post #33

It's nice to have this in the standard library, but it doesn't solve any existing pain points around structured log metadata and contexts. We use zap [0] and store a zap logger on the request context which allows different parts of the request pipeline to log with things like tenantId, traceId, and correlationId automatically appended. But getting a logger off the context is annoying, leads to inconsistent logging pr…

log/slog package essentially delegates writing log messages to some "handler" interface. The key method is: Handle(context.Context, Record) error This method has access to the context, which means you can get the logging handler to extract values from the context. Instead of storing the logger on the context, you can extract the traceId, etc values from the context and log those. It's a little bit involved to write a…

Here's an example of extracting context values in a custom slog handler:

https://github.com/indexsupply/x/blob/main/wslog/slog_test.g...

Re: Structured logging with slog

#68
post #28

The new structured logging library is a great addition, its nice to have structured logging in the standard lib. It's easy to get started with log/slog and one of the built in handlers, but as soon as you want to change something the library design pushes you towards implementing an entire handler. For example, if I want the built in JSON format, but with a different formatting of the Time field, that's not easy to d…

Nice middleware package. I have to admit, the `log.InfoContext(ctx,...` style of redundancy that permeates the standard lib at this point is really gross, especially given that the most common use case for go is going to have contexts everywhere.

Go’s decision to not support function overloading leads to a tonne of really ugly APIs. Obviously every decision in language design is a tradeoff, but IMO they made the wrong call here.

Re: Structured logging with slog

#69

I'm really glad they've introduced this, I just wish it also had the traditional formatting methods, eg Infof, Debugf, Errorf, etc, for backwards compatibility. I've got a few packages that accept a basic logger interface, eg: type debugLogger interface { Debugf(format string, args ...any) } type MyThing struct { logger debugLogger } func New(logger debugLogger) *MyThing { return &MyThing{logger} } I'd love to switch…

I would defend slog's decision there. Infof/Debugf/Errorf are like fine especially when I'm making a little CLI tool for myself, but my main consumption of logs at work is other peoples' logs via a cloud log aggregator, and so when you give other devs who are not me Sprintf they start to do things like "[%s] default/%v - %v" or so, which makes sense to them but doesn't give me great strings to search for when I'm trying to figure out "what were all of the situations in which this strange thing happened".

It's like when you're trying to internationalize, you want to emit as constant of a string as reasonably practical, so that it can be straightforwardly matched and substituted into a different language. Except in this case that different language is regexes being used to change the thing into a SQL statement to fix the mess (or whatever).

So much easier to say "stop trying to Sprintf your logs, just add the values as key-value pairs at the end of the function call."

Re: Structured logging with slog

#70
post #35
post #4

The rationale: > With many structured logging packages to choose from, large programs will often end up including more than one through their dependencies. The main program might have to configure each of these logging packages so that the log output is consistent: it all goes to the same place, in the same format. By including structured logging in the standard library, we can provide a common framework that all the…

Rust seems to do find with a de-facto logging library, and the Java ecosystem seems to have converged on a common API, but with a lot of effort I think.

PHP did so with PSR-3 as well https://www.php-fig.org/psr/psr-3/.
Post reply on HN