diff --git a/array_go118.go b/array_go118.go index db36ec37f..4af3d480e 100644 --- a/array_go118.go +++ b/array_go118.go @@ -23,7 +23,11 @@ package zap -import "go.uber.org/zap/zapcore" +import ( + "fmt" + + "go.uber.org/zap/zapcore" +) // Objects constructs a field with the given key, holding a list of the // provided objects that can be marshaled by Zap. @@ -122,3 +126,27 @@ func (os objectValues[T, P]) MarshalLogArray(arr zapcore.ArrayEncoder) error { } return nil } + +// Stringers constructs a field with the given key, holding a list of the +// output provided by the value's String method +// +// Given an object that implements String on the value receiver, you +// can log a slice of those objects with Objects like so: +// +// type Request struct{ ... } +// func (a Request) String() string +// +// var requests []Request = ... +// logger.Info("sending requests", zap.Stringers("requests", requests)) +func Stringers[T fmt.Stringer](key string, values []T) Field { + return Array(key, stringers[T](values)) +} + +type stringers[T fmt.Stringer] []T + +func (ss stringers[T]) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for _, s := range ss { + arr.AppendString(s.String()) + } + return nil +} diff --git a/array_go118_test.go b/array_go118_test.go index 54eedaaf4..30c115f93 100644 --- a/array_go118_test.go +++ b/array_go118_test.go @@ -179,3 +179,48 @@ func TestObjectsAndObjectValues_marshalError(t *testing.T) { }) } } + +type stringerObject struct{ + value string +} + +func (s stringerObject) String() string { + return s.value +} + +func TestStringers(t *testing.T) { + t.Parallel() + + tests := []struct { + desc string + give Field + want []any + }{ + { + desc: "Stringers", + give: Stringers("", []stringerObject{ + {value: "foo"}, + {value: "bar"}, + {value: "baz"}, + }), + want: []any{ + "foo", + "bar", + "baz", + }, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.desc, func(t *testing.T) { + t.Parallel() + + tt.give.Key = "k" + + enc := zapcore.NewMapObjectEncoder() + tt.give.AddTo(enc) + assert.Equal(t, tt.want, enc.Fields["k"]) + }) + } +}