slog: call Value.Resolve so Handlers don't have to

Resolving a slog.Value means calling its LogValue method,
if there is one, and using the resulting Value instead.

Up until now, it has been the Handler's responsibility to call
Resolve. This CL moves that responsibility to the slog package.

Besides easing the burden on Handler writers, this change also
guarantees deterministic behavior. If different Handlers resolved a
Value at different points during processing, and the LogValuer's
result was time-dependent, then the results could differ. This mainly
concerns the attributes passed to Logger.With. They should be resolved
during that call, since they will probably be used in multiple log
events and it would be wasteful to re-invoke LogValue for each event.
Logger.With now resolves the attributes before passing them to
Handler.WithAttrs, removing the possibility of a Handler getting this
wrong.

Record.AddAttrs now also resolves its aguments before adding them to
the Record.

The Value.Resolve method still has its uses, so we leave it exported.
One use, demonstrated by the built-in handlers, is to resolve
attributes returned by a user-supplied function like
HandlerOptions.ReplaceAttr.

To anticpate a question: why don't we resolve even earlier, when a
Value is first created? One purpose of this mechanism is to delay
computation until it is sure to be useful. So we don't want to resolve
a Value before Handler.Enabled has returned true.

Change-Id: I61c4380f381b40c338ca0b3eea44e12a2c6a2192
Reviewed-on: https://go-review.googlesource.com/c/exp/+/464100
Run-TryBot: Jonathan Amsterdam <jba@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Alan Donovan <adonovan@google.com>
6 files changed
tree: 5b10d51aec35cb7fa15bde01339c4a4d11bce45e
  1. apidiff/
  2. cmd/
  3. constraints/
  4. devtools/
  5. ebnf/
  6. ebnflint/
  7. errors/
  8. event/
  9. inotify/
  10. io/
  11. jsonrpc2/
  12. maps/
  13. mmap/
  14. rand/
  15. shiny/
  16. shootout/
  17. slices/
  18. slog/
  19. sumdb/
  20. typeparams/
  21. utf8string/
  22. .gitattributes
  23. .gitignore
  24. codereview.cfg
  25. CONTRIBUTING.md
  26. go.mod
  27. go.sum
  28. LICENSE
  29. PATENTS
  30. README.md
README.md

exp

PkgGoDev

This subrepository holds experimental and deprecated (in the old directory) packages.

The idea for this subrepository originated as the pkg/exp directory of the main repository, but its presence there made it unavailable to users of the binary downloads of the Go installation. The subrepository has therefore been created to make it possible to go get these packages.

Warning: Packages here are experimental and unreliable. Some may one day be promoted to the main repository or other subrepository, or they may be modified arbitrarily or even disappear altogether.

In short, code in this subrepository is not subject to the Go 1 compatibility promise. (No subrepo is, but the promise is even more likely to be violated by go.exp than the others.)

Caveat emptor.