slog: define a removeTime function for examples

Since examples with output need to be deterministic, they remove
the time attribute with a ReplaceAttr function.

Define a removeTime function at top level so examples can use it.

Change-Id: Id759a596deee49bbf66b1c6a3079f19805ae6ab5
Reviewed-on: https://go-review.googlesource.com/c/exp/+/464855
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
index 948271e..7f82e19 100644
--- a/slog/example_level_handler_test.go
+++ b/slog/example_level_handler_test.go
@@ -9,6 +9,7 @@
 	"os"
 
 	"golang.org/x/exp/slog"
+	"golang.org/x/exp/slog/internal/testutil"
 )
 
 // A LevelHandler wraps a Handler with an Enabled method
@@ -63,16 +64,7 @@
 // Another typical use would be to decrease the log level (to LevelDebug, say)
 // during a part of the program that was suspected of containing a bug.
 func ExampleHandler_levelHandler() {
-	th := slog.HandlerOptions{
-		// Remove time from the output.
-		ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
-			if a.Key == slog.TimeKey {
-				return slog.Attr{}
-			}
-			return a
-		},
-	}.NewTextHandler(os.Stdout)
-
+	th := slog.HandlerOptions{ReplaceAttr: testutil.RemoveTime}.NewTextHandler(os.Stdout)
 	logger := slog.New(NewLevelHandler(slog.LevelWarn, th))
 	logger.Info("not printed")
 	logger.Warn("printed")
diff --git a/slog/example_logvaluer_secret_test.go b/slog/example_logvaluer_secret_test.go
index aa6c704..f3e8fec 100644
--- a/slog/example_logvaluer_secret_test.go
+++ b/slog/example_logvaluer_secret_test.go
@@ -8,6 +8,7 @@
 	"os"
 
 	"golang.org/x/exp/slog"
+	"golang.org/x/exp/slog/internal/testutil"
 )
 
 // A token is a secret value that grants permissions.
@@ -23,14 +24,8 @@
 // with an alternative representation to avoid revealing secrets.
 func ExampleLogValuer_secret() {
 	t := Token("shhhh!")
-	// Remove the time attribute to make Output deterministic.
-	removeTime := func(groups []string, a slog.Attr) slog.Attr {
-		if a.Key == slog.TimeKey && len(groups) == 0 {
-			a.Key = ""
-		}
-		return a
-	}
-	logger := slog.New(slog.HandlerOptions{ReplaceAttr: removeTime}.NewTextHandler(os.Stdout))
+	logger := slog.New(slog.HandlerOptions{ReplaceAttr: testutil.RemoveTime}.
+		NewTextHandler(os.Stdout))
 	logger.Info("permission granted", "user", "Perry", "token", t)
 
 	// Output:
diff --git a/slog/example_test.go b/slog/example_test.go
index 05938dc..e777f2d 100644
--- a/slog/example_test.go
+++ b/slog/example_test.go
@@ -10,20 +10,14 @@
 	"time"
 
 	"golang.org/x/exp/slog"
+	"golang.org/x/exp/slog/internal/testutil"
 )
 
 func ExampleGroup() {
 	r, _ := http.NewRequest("GET", "localhost", nil)
 	// ...
 
-	// Remove the time attribute to make Output deterministic.
-	removeTime := func(groups []string, a slog.Attr) slog.Attr {
-		if a.Key == slog.TimeKey && len(groups) == 0 {
-			a.Key = ""
-		}
-		return a
-	}
-	logger := slog.New(slog.HandlerOptions{ReplaceAttr: removeTime}.NewTextHandler(os.Stdout))
+	logger := slog.New(slog.HandlerOptions{ReplaceAttr: testutil.RemoveTime}.NewTextHandler(os.Stdout))
 	slog.SetDefault(logger)
 
 	slog.Info("finished",
diff --git a/slog/internal/testutil/testutil.go b/slog/internal/testutil/testutil.go
new file mode 100644
index 0000000..4f59d0a
--- /dev/null
+++ b/slog/internal/testutil/testutil.go
@@ -0,0 +1,18 @@
+// 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 testutil contains support functions for testing.
+package testutil
+
+import "golang.org/x/exp/slog"
+
+// RemoveTime removes the top-level time attribute.
+// It is intended to be used as a ReplaceAttr function,
+// to make example output deterministic.
+func RemoveTime(groups []string, a slog.Attr) slog.Attr {
+	if a.Key == slog.TimeKey && len(groups) == 0 {
+		a.Key = ""
+	}
+	return a
+}