slog: document HandlerOptions and groups

Change-Id: If4bf0e1b53ebc6b5ffa500f64dd4056a184062a6
Reviewed-on: https://go-review.googlesource.com/c/exp/+/456621
Run-TryBot: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/slog/doc.go b/slog/doc.go
index ed32e0c..7f483b6 100644
--- a/slog/doc.go
+++ b/slog/doc.go
@@ -38,7 +38,7 @@
 default logger.
 
 The default handler formats the log record's message, time, level, and attributes
-as a string and passes it to the [log] package."
+as a string and passes it to the [log] package.
 
     2022/11/08 15:28:26 INFO hello count=3
 
@@ -66,6 +66,11 @@
 
     {"time":"2022-11-08T15:28:26.000000000-05:00","level":"INFO","msg":"hello","count":3}
 
+Both [TextHandler] and [JSONHandler] can be configured with a [HandlerOptions].
+There are options for setting the minimum level (see Levels, below),
+displaying the source file and line of the log call, and
+modifying attributes before they are logged.
+
 Setting a logger as the default with
 
     slog.SetDefault(logger)
@@ -108,12 +113,25 @@
 
     slog.Info("hello", "count", 3)
 
+Some attributes are common to many log calls.
+For example, you may wish to include the URL or trace identifier of a server request
+with all log events arising from the request.
+Rather than repeat the attribute with every log call, you can use [Logger.With]
+to construct a new Logger containing the attributes:
+
+    logger2 := logger.With("url", r.URL)
+
+The arguments to With are the same key-value pairs used in [Logger.Info].
+The result is a new Logger with the same handler as the original, but additional
+attributes that will appear in the output of every call.
+
+
 
 # Levels
 
 A [Level] is an integer representing the importance or severity of a log event.
 The higher the level, the more severe the event.
-This package defines four constants for the most common levels,
+This package defines constants for the most common levels,
 but any int can be used as a level.
 
 In an application, you may wish to log messages only at a certain level or greater.
@@ -122,6 +140,7 @@
 The built-in handlers can be configured with the minimum level to output by
 setting [HandlerOptions.Level].
 The program's `main` function typically does this.
+The default value is LevelInfo.
 
 Setting the [HandlerOptions.Level] field to a [Level] value
 fixes the handler's minimum level throughout its lifetime.
@@ -143,16 +162,51 @@
     programLevel.Set(slog.LevelDebug)
 
 
-# Configuring the built-in handlers
-
-TODO: cover HandlerOptions
-
 # Groups
 
+Attributes can be collected into groups.
+A group has a name that is used to qualify the names of its attributes.
+How this qualification is displayed depends on the handler.
+[TextHandler] separates the group and attribute names with a dot.
+[JSONHandler] treats each group as a separate JSON object, with the group name as the key.
+
+Use [Group] to create a Group Attr from a name and a list of Attrs:
+
+    slog.Group("request",
+        slog.String("method", r.Method),
+        slog.Any("url", r.URL))
+
+TextHandler would display this group as
+
+    request.method=GET request.url=http://example.com
+
+JSONHandler would display it as
+
+    "request":{"method":"GET","url":"http://example.com"}
+
+Use [Logger.WithGroup] to qualify all of a Logger's output
+with a group name. Calling WithGroup on a Logger results in a
+new Logger with the same Handler as the original, but with all
+its attributes qualified by the group name.
+
+This can help prevent duplicate attribute keys in large systems,
+where subsystems might use the same keys.
+Pass each subsystem a different Logger with its own group name so that
+potential duplicates are qualified:
+
+    logger := slog.Default().With("id", systemID)
+    parserLogger := logger.WithGroup("parser")
+    parseInput(input, parserLogger)
+
+When parseInput logs with parserLogger, its keys will be qualified with "parser",
+so even if it uses the common key "id", the log line will have distinct keys.
+
 # Contexts
 
 # Advanced topics
 
+
+
 ## Customizing a type's logging behavior
 
 TODO: discuss LogValuer
@@ -165,6 +219,11 @@
 
 TODO: discuss NewRecord, Record.AddAttrs
 
+## Performance considerations
+
+TODO: mention to avoid unnecessary work (like calling URL.String()) in log args in case
+the log statement is disabled.
+
 ## Writing a handler
 
 */