From fe97bedf671d3e9761403bfa4ee44a605687bb2a Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 13 May 2020 14:47:13 -0700 Subject: [PATCH] types/logger: add ArgWriter --- types/logger/logger.go | 16 ++++++++++++++++ types/logger/logger_test.go | 15 +++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/types/logger/logger.go b/types/logger/logger.go index f5a37c714..9e4bc72d9 100644 --- a/types/logger/logger.go +++ b/types/logger/logger.go @@ -8,9 +8,11 @@ package logger import ( + "bufio" "container/list" "fmt" "io" + "io/ioutil" "log" "sync" @@ -111,3 +113,17 @@ func RateLimitedFn(logf Logf, f float64, burst int, maxCache int) Logf { } } } + +// ArgWriter is a fmt.Formatter that can be passed to any Logf func to +// efficiently write to a %v argument without allocations. +type ArgWriter func(*bufio.Writer) + +func (fn ArgWriter) Format(f fmt.State, _ rune) { + bw := argBufioPool.Get().(*bufio.Writer) + bw.Reset(f) + fn(bw) + bw.Flush() + argBufioPool.Put(bw) +} + +var argBufioPool = &sync.Pool{New: func() interface{} { return bufio.NewWriterSize(ioutil.Discard, 1024) }} diff --git a/types/logger/logger_test.go b/types/logger/logger_test.go index 1f7ab4f07..bd4470875 100644 --- a/types/logger/logger_test.go +++ b/types/logger/logger_test.go @@ -5,6 +5,8 @@ package logger import ( + "bufio" + "bytes" "fmt" "log" "testing" @@ -62,3 +64,16 @@ func TestRateLimiter(t *testing.T) { } } + +func TestArgWriter(t *testing.T) { + got := new(bytes.Buffer) + fmt.Fprintf(got, "Greeting: %v", ArgWriter(func(bw *bufio.Writer) { + bw.WriteString("Hello, ") + bw.WriteString("world") + bw.WriteByte('!') + })) + const want = "Greeting: Hello, world!" + if got.String() != want { + t.Errorf("got %q; want %q", got, want) + } +}