Skip to content

Commit 3d61de4

Browse files
earthboundkidgopherbot
authored andcommitted
log/slog: add DiscardHandler
This adds a package-level variable, slog.DiscardHandler, which is a slog.Handler which performs no output. This serves a similar purpose to io.Discard. Fixes #62005 Change-Id: Ia8babc55f860dec9b663a5c400090a7669608fd5 GitHub-Last-Rev: 0a61117 GitHub-Pull-Request: #70296 Reviewed-on: https://go-review.googlesource.com/c/go/+/626486 Auto-Submit: Ian Lance Taylor <iant@golang.org> Reviewed-by: Jonathan Amsterdam <jba@google.com> Reviewed-by: Carlos Amedee <carlos@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
1 parent cd35323 commit 3d61de4

File tree

6 files changed

+67
-11
lines changed

6 files changed

+67
-11
lines changed

api/next/62005.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pkg log/slog, var DiscardHandler Handler #62005
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The new [DiscardHandler] is a handler that is never enabled and always discards its output.

src/log/slog/example_discard_test.go

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package slog_test
2+
3+
import (
4+
"log/slog"
5+
"log/slog/internal/slogtest"
6+
"os"
7+
)
8+
9+
func ExampleDiscardHandler() {
10+
// A slog.TextHandler can output log messages.
11+
logger1 := slog.New(slog.NewTextHandler(
12+
os.Stdout,
13+
&slog.HandlerOptions{ReplaceAttr: slogtest.RemoveTime},
14+
))
15+
logger1.Info("message 1")
16+
17+
// A slog.DiscardHandler will discard all messages.
18+
logger2 := slog.New(slog.DiscardHandler)
19+
logger2.Info("message 2")
20+
21+
// Output:
22+
// level=INFO msg="message 1"
23+
}

src/log/slog/handler.go

+11
Original file line numberDiff line numberDiff line change
@@ -602,3 +602,14 @@ func appendRFC3339Millis(b []byte, t time.Time) []byte {
602602
b = append(b[:n+prefixLen], b[n+prefixLen+1:]...) // drop the 4th digit
603603
return b
604604
}
605+
606+
// DiscardHandler discards all log output.
607+
// DiscardHandler.Enabled returns false for all Levels.
608+
var DiscardHandler Handler = discardHandler{}
609+
610+
type discardHandler struct{}
611+
612+
func (dh discardHandler) Enabled(context.Context, Level) bool { return false }
613+
func (dh discardHandler) Handle(context.Context, Record) error { return nil }
614+
func (dh discardHandler) WithAttrs(attrs []Attr) Handler { return dh }
615+
func (dh discardHandler) WithGroup(name string) Handler { return dh }

src/log/slog/handler_test.go

+21
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"context"
1212
"encoding/json"
1313
"io"
14+
"os"
1415
"path/filepath"
1516
"slices"
1617
"strconv"
@@ -711,3 +712,23 @@ func BenchmarkWriteTime(b *testing.B) {
711712
buf = appendRFC3339Millis(buf[:0], tm)
712713
}
713714
}
715+
716+
func TestDiscardHandler(t *testing.T) {
717+
ctx := context.Background()
718+
stdout, stderr := os.Stdout, os.Stderr
719+
os.Stdout, os.Stderr = nil, nil // panic on write
720+
t.Cleanup(func() {
721+
os.Stdout, os.Stderr = stdout, stderr
722+
})
723+
724+
// Just ensure nothing panics during normal usage
725+
l := New(DiscardHandler)
726+
l.Info("msg", "a", 1, "b", 2)
727+
l.Debug("bg", Int("a", 1), "b", 2)
728+
l.Warn("w", Duration("dur", 3*time.Second))
729+
l.Error("bad", "a", 1)
730+
l.Log(ctx, LevelWarn+1, "w", Int("a", 1), String("b", "two"))
731+
l.LogAttrs(ctx, LevelInfo+1, "a b c", Int("a", 1), String("b", "two"))
732+
l.Info("info", "a", []Attr{Int("i", 1)})
733+
l.Info("info", "a", GroupValue(Int("i", 1)))
734+
}

src/log/slog/logger_test.go

+10-11
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ func TestCallDepth(t *testing.T) {
231231

232232
func TestAlloc(t *testing.T) {
233233
ctx := context.Background()
234-
dl := New(discardHandler{})
234+
dl := New(discardTestHandler{})
235235
defer SetDefault(Default()) // restore
236236
SetDefault(dl)
237237

@@ -258,7 +258,7 @@ func TestAlloc(t *testing.T) {
258258
})
259259
})
260260
t.Run("2 pairs disabled inline", func(t *testing.T) {
261-
l := New(discardHandler{disabled: true})
261+
l := New(DiscardHandler)
262262
s := "abc"
263263
i := 2000
264264
wantAllocs(t, 2, func() {
@@ -269,7 +269,7 @@ func TestAlloc(t *testing.T) {
269269
})
270270
})
271271
t.Run("2 pairs disabled", func(t *testing.T) {
272-
l := New(discardHandler{disabled: true})
272+
l := New(DiscardHandler)
273273
s := "abc"
274274
i := 2000
275275
wantAllocs(t, 0, func() {
@@ -305,7 +305,7 @@ func TestAlloc(t *testing.T) {
305305
})
306306
})
307307
t.Run("attrs3 disabled", func(t *testing.T) {
308-
logger := New(discardHandler{disabled: true})
308+
logger := New(DiscardHandler)
309309
wantAllocs(t, 0, func() {
310310
logger.LogAttrs(ctx, LevelInfo, "hello", Int("a", 1), String("b", "two"), Duration("c", time.Second))
311311
})
@@ -568,18 +568,17 @@ func (c *captureHandler) clear() {
568568
c.r = Record{}
569569
}
570570

571-
type discardHandler struct {
572-
disabled bool
573-
attrs []Attr
571+
type discardTestHandler struct {
572+
attrs []Attr
574573
}
575574

576-
func (d discardHandler) Enabled(context.Context, Level) bool { return !d.disabled }
577-
func (discardHandler) Handle(context.Context, Record) error { return nil }
578-
func (d discardHandler) WithAttrs(as []Attr) Handler {
575+
func (d discardTestHandler) Enabled(context.Context, Level) bool { return true }
576+
func (discardTestHandler) Handle(context.Context, Record) error { return nil }
577+
func (d discardTestHandler) WithAttrs(as []Attr) Handler {
579578
d.attrs = concat(d.attrs, as)
580579
return d
581580
}
582-
func (h discardHandler) WithGroup(name string) Handler {
581+
func (h discardTestHandler) WithGroup(name string) Handler {
583582
return h
584583
}
585584

0 commit comments

Comments
 (0)