slog: add LevelHandler example

Add an example that defines LevelHandler, a Handler wraps another
Handler and enforces a minimum level.

Change-Id: I009b9f39d0b873ed1067e0fa90c838e8afc36f9e
Reviewed-on: https://go-review.googlesource.com/c/exp/+/447965
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
diff --git a/slog/example_level_handler_test.go b/slog/example_level_handler_test.go
new file mode 100644
index 0000000..17a20d2
--- /dev/null
+++ b/slog/example_level_handler_test.go
@@ -0,0 +1,73 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package slog_test
+
+import (
+	"os"
+
+	"golang.org/x/exp/slog"
+)
+
+// A LevelHandler wraps a Handler with an Enabled method
+// that returns false for levels below a minimum.
+type LevelHandler struct {
+	level   slog.Leveler
+	handler slog.Handler
+}
+
+// NewLevelHandler returns a LevelHandler with the given level.
+// All methods except Enabled delegate to h.
+func NewLevelHandler(level slog.Leveler, h slog.Handler) *LevelHandler {
+	// Optimization: avoid chains of LevelHandlers.
+	if lh, ok := h.(*LevelHandler); ok {
+		h = lh.Handler()
+	}
+	return &LevelHandler{level, h}
+}
+
+// Enabled implements Handler.Enabled by reporting whether
+// level is at least as large as h's level.
+func (h *LevelHandler) Enabled(level slog.Level) bool {
+	return level >= h.level.Level()
+}
+
+// Handle implements Handler.Handle.
+func (h *LevelHandler) Handle(r slog.Record) error {
+	return h.handler.Handle(r)
+}
+
+// WithAttrs implements Handler.WithAttrs.
+func (h *LevelHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
+	return NewLevelHandler(h.level, h.handler.WithAttrs(attrs))
+}
+
+// WithGroup implements Handler.WithGroup.
+func (h *LevelHandler) WithGroup(name string) slog.Handler {
+	return NewLevelHandler(h.level, h.handler.WithGroup(name))
+}
+
+// Handler returns the Handler wrapped by h.
+func (h *LevelHandler) Handler() slog.Handler {
+	return h.handler
+}
+
+func ExampleHandler_levelHandler() {
+	th := slog.HandlerOptions{
+		// Remove time from the output.
+		ReplaceAttr: func(a slog.Attr) slog.Attr {
+			if a.Key == slog.TimeKey {
+				return slog.Attr{}
+			}
+			return a
+		},
+	}.NewTextHandler(os.Stdout)
+
+	logger := slog.New(NewLevelHandler(slog.WarnLevel, th))
+	logger.Info("not printed")
+	logger.Warn("printed")
+
+	// Output:
+	// level=WARN msg=printed
+}