4 ms·
There is no reason to distinguish a Handler from a Logger. A Handler is just a Logger which has a side effect, nothing more. There is no reason to distinguish
by kiitos 3y ago
There is no reason to distinguish a Handler from a Logger. A Handler is just a Logger which has a side effect, nothing more.
There is no reason to distinguish an Attr or Group or Record from a (set of) KeyValuePairs. They're all the same thing.
And I don't agree that Zap is the most popular structured logging library. It's one of many, none are the clear winner.
But, whatever.
- morelisp 3y ago> There is no reason to distinguish a Handler from a Logger. A Handler is an abstract type, a Logger is a concrete one. A Logger lets you have a large user surface (and without virtual calls); and Handler, a small implementer surface. (The handler is not much beyond what you proposed, plus an optimization to avoid materializing complete record+KV pairs if the level isn't met.) The concepts also map fairly directly to logrus and zerolog (which has an absolutely enormous surface to avoid boxing).
- kiitos 3y agoIf slog needs to avoid virtual calls or boxing or whatever else for reasons of performance, I guess I feel very strongly that it should do so in a way that doesn't impact users, and shouldn't let these concerns influence the API design.
- morelisp 3y ago"Ignore performance when designing your API" is an obvious non-starter. I don't think you're serious. More specifically, users want the surface area Logger has. They do not want a single function with a complex object specification, just like they don't want a function per type.
- kiitos 3y agoThere is obviously an enormous difference between "don't let performance influence your API (to become awkward or nonidiomatic)" and "ignore performance when designing your API".
- morelisp 3y agoBut you've offered no actual criteria why the API is bad! Again, most logging users want something to handle nested record contexts for them and per-level methods, most logging implementers want a minimum number of entry points, and that's exactly what this API offers. (It's definitely not zerolog-style where it sacrifices ease of use for performance.)
- kiitos 3y agoStructured logging means logging where discrete events are sets of key=val pairs, and nothing more. What is a record context? What is a level? These are concepts built on top of a structured logger, which manifest as specific key=val pairs in a given structured log event. They don't need -- and shouldn't have! -- first-order representation in a low-level structured logger API. What is an entry point? If I'm writing some structured logger implementation, I expect that I should need to provide precisely one method: func (x *MyThing) Log(<set of key=val pairs>) error Anything more is cruft.
- kiitos 3y agoI don't think so. A Handler is something that transforms log events to concrete outputs (files, disks, writes to stderr, etc.) via side effects. A Logger is what programs use to produce, transform, etc. log events. Both are abstract interfaces with arbitrarily many possible implementations. Both are defined in terms of their user-facing capabilities. I'm not sure how those definitions would differ. Both accept log events and do something with them. That interface is the same.
- akshayshah 3y agoZap author here :) Logrus remains quite a bit more popular than zap. (Does anyone remember the epic tire fire when Sirupsen briefly changed the casing of his GitHub username?) From my perspective, the problem with the KeyValuePairs API is that it’s inescapably slow and allocation-heavy. I’m glad that a logging API built into the standard library is usable in more performance-sensitive contexts. It’s easy enough to wrap it up in a KeyValuePairs-style API if you’d prefer that, and you’ll now have the ability to unwrap your logger and interop with other libraries that expect the standard slog interface.