Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a slightly slower, but less verbose, logger #138

Closed
akshayjshah opened this issue Sep 17, 2016 · 6 comments
Closed

Add a slightly slower, but less verbose, logger #138

akshayjshah opened this issue Sep 17, 2016 · 6 comments
Assignees

Comments

@akshayjshah
Copy link
Contributor

zap.Logger is really fast, but it's quite verbose - users must repeatedly reference the zap package. This is a good trade-off for performance-critical applications, but it's not good for most users. Consider the impression that this snippet from the README leaves on potential users and contributors:

logger.Info("Failed to fetch URL.",
  zap.String("url", url),
  zap.Int("attempt", tryNum),
  zap.Duration("backoff", sleepFor),
)

The wrapper provided by the zbark sub-package is great for our internal use, since we're using the bark.Logger interface all over. However, it's also unpleasantly verbose:

logger.WithFields(bark.Fields{
    "url": url,
    "attempt": tryNum,
    "backoff": sleepFor,
}).Info("Failed to fetch URL.")

To show off how easy it is to write a clean wrapper on top of the core zap.Logger type, spur adoption, and generally make a better impression on first-time users, I'd like to include a higher-level zap.SugaredLogger (name TBD - we could even rename the current logger to CoreLogger and call the new thing Logger). I'm open to other ideas, but I'd like something similar to the log15 API:

logger := zap.Sugar(coreLogger)
logger.Info("Failed to fetch URL",
    "url", url,
    "attempt", tryNum,
    "backoff", sleepFor,
)
anotherCoreLogger := zap.Desugar(logger)
mikluko added a commit to mikluko/zap that referenced this issue Sep 22, 2016
@ascandella
Copy link

ascandella commented Sep 25, 2016

Looks like @akabos is working on this in #147

akshayjshah pushed a commit that referenced this issue Nov 21, 2016
@jcorbin jcorbin added this to the 1.0.0 milestone Jan 3, 2017
@akshayjshah akshayjshah self-assigned this Jan 3, 2017
@tesujimath
Copy link

This issue seems unwarranted to me, for the following reason. Rather than sprinkle ad-hoc strings around the code for the field names, I think it is better to wrap all fields to be logged in some trivial functions, which I define in one place, e.g.

func logUser(id account.AccountId) zap.Field      { return zap.Int("user", int(id)) }
func logNUsers(n int) zap.Field                   { return zap.Int("n-users", n) }
func logSession(session int) zap.Field            { return zap.Int("session", session) }

This has these benefits:

  1. The catalogue of field names is defined in one place, rather than implicitly all over the application.
  2. It protects against typos in field names, which could easily occur with ad-hoc strings.
  3. It really cleans up logging invocations (below)
  4. Much better performance than some sugared approach using interfaces (I suspect)

So, with this approach, I log an event as follows:

logger.Debug("Logoff", logUser(id0), logSession(sessionId), logNUsers(t.nOnline))

What do you think?

@akshayjshah
Copy link
Contributor Author

@tesujimath While I agree that the scheme you've proposed is reasonable, I don't think it affects this issue. This issue is about adding an optional wrapper around the main Logger type to provide a less-verbose API. Many people prefer their logger APIs to be less safe, but also less verbose, and I'd like to provide an option to them.

If that API isn't to your taste, don't use the wrapper ;)

@tesujimath
Copy link

@akshayjshah I'm afraid I don't see the use for the sugared API. You mention verbosity again, but the scheme I propose has the same verbosity as the sugared approach (it's just faster and safer). If the goal is to support ad-hoc logging, with unplanned field names, I concede the sugared API is better in that respect. ;-)

But I don't really see how anyone would process their logfile without having a record somewhere of what fields it may contain. (Just like with unstructured logging.)

Of course anyone can write a sugared API wrapper, and I don't really care. But would you at least be open to a pull request for a new section in the README describing my scheme? So that anyone who is thinking of using the sugared API at least understands the other option.

@akshayjshah
Copy link
Contributor Author

@tesujimath We'll have to agree to disagree on this. I'd prefer to keep the README and docs as-is; as the package author, I'd prefer to highlight the LogMarshaler API for these sorts of use cases. However, I'm happy that you've found a scheme that works well for you.

akshayjshah pushed a commit that referenced this issue Jan 13, 2017
akshayjshah pushed a commit that referenced this issue Jan 13, 2017
akshayjshah pushed a commit that referenced this issue Jan 19, 2017
@akshayjshah
Copy link
Contributor Author

Landed on dev.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

4 participants