I don’t mind it. You can use LogAttrs if you want to be explicit.
Although I do wonder if there’s anything tricky with the type system that is preventing something like this from being supported: https://go.dev/play/p/_YV7sYdnZ5V
Just my opinions here. I don’t question the value of slog as it sits, just could have been better for the community at large is all.
The reason it doesn’t use maps is that maps are significantly slower, TFA has an entire section on performances.
However if you prefer that interface and don’t mind the performance hit, nothing precludes writing your own Logger (it’s just a façade over the Handler interface) and taking maps.
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 Pythons approach where you can have user="value" it makes things a bit more clear.
The trouble is, Go doesn't have keyword parameters so that doesn't work.
It would definitely not be better from the point of view of
> We wanted slog to be fast.
Most log metadata will be attached by libraries and middleware, so service/application devs won't even see most of it.
json_build_object ( VARIADIC "any" ) → json
jsonb_build_object ( VARIADIC "any" ) → jsonb
Builds a JSON object out of a variadic argument list.
By convention, the argument list consists of alternating keys and values.
Key arguments are coerced to text; value arguments are converted as per to_json or to_jsonb.
json_build_object('foo', 1, 2, row(3,'bar')) → {"foo" : 1, "2" : {"f1":3,"f2":"bar"}} json_build_object(
'foo', 1,
2, row(3, 'bar')
) logger.Info("failed to fetch URL",
// Structured context as strongly typed Field values.
zap.String("url", url),
zap.Int("attempt", 3),
zap.Duration("backoff", time.Second),
)
They also have zap.Error(err) which generates the "error" key as a convention. sugar.Infow("failed to fetch URL",
"url", "http://example.com",
"attempt", 3,
"backoff", time.Second,
)
Really slog presents mostly the same two APIs as Zap, with a single entrypoint.For example: https://pkg.go.dev/golang.org/x/exp/slog#example-Group
use slog::info;
...
info!("hello, world"; "user" => os.Getenv("USER"));For better or for worse, Go doesn’t have that.
my %hash = (
Foo => “bar”,
Baz => “qux”,
);
the behaviour is no different than my %hash = (
Foo, “bar”,
Baz, “qux”,
);
it’s just that a literal plist in a hash context is interpreted as a hash.Hence “=>” being called “fat comma” in perl.
Which means you can writer
my %h = (a => b => c => d);
or my %h = (a, b => c, d);
they all mean the same thing. slog.Info("hello, world", slog.String("user", os.Getenv("USER")))
[1]: https://pkg.go.dev/log/slog#hdr-Attrs_and_Values
I really like Pythons approach where you can have user="value" it makes things a bit more clear.