// Copyright (c) 2016 Uber Technologies, Inc.1//2// Permission is hereby granted, free of charge, to any person obtaining a copy3// of this software and associated documentation files (the "Software"), to deal4// in the Software without restriction, including without limitation the rights5// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell6// copies of the Software, and to permit persons to whom the Software is7// furnished to do so, subject to the following conditions:8//9// The above copyright notice and this permission notice shall be included in10// all copies or substantial portions of the Software.11//12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR13// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,14// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE15// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER16// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,17// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN18// THE SOFTWARE.1920package zap2122import (23"fmt"24"time"2526"go.uber.org/zap/zapcore"27)2829// Array constructs a field with the given key and ArrayMarshaler. It provides30// a flexible, but still type-safe and efficient, way to add array-like types31// to the logging context. The struct's MarshalLogArray method is called lazily.32func Array(key string, val zapcore.ArrayMarshaler) Field {33return Field{Key: key, Type: zapcore.ArrayMarshalerType, Interface: val}34}3536// Bools constructs a field that carries a slice of bools.37func Bools(key string, bs []bool) Field {38return Array(key, bools(bs))39}4041// ByteStrings constructs a field that carries a slice of []byte, each of which42// must be UTF-8 encoded text.43func ByteStrings(key string, bss [][]byte) Field {44return Array(key, byteStringsArray(bss))45}4647// Complex128s constructs a field that carries a slice of complex numbers.48func Complex128s(key string, nums []complex128) Field {49return Array(key, complex128s(nums))50}5152// Complex64s constructs a field that carries a slice of complex numbers.53func Complex64s(key string, nums []complex64) Field {54return Array(key, complex64s(nums))55}5657// Durations constructs a field that carries a slice of time.Durations.58func Durations(key string, ds []time.Duration) Field {59return Array(key, durations(ds))60}6162// Float64s constructs a field that carries a slice of floats.63func Float64s(key string, nums []float64) Field {64return Array(key, float64s(nums))65}6667// Float32s constructs a field that carries a slice of floats.68func Float32s(key string, nums []float32) Field {69return Array(key, float32s(nums))70}7172// Ints constructs a field that carries a slice of integers.73func Ints(key string, nums []int) Field {74return Array(key, ints(nums))75}7677// Int64s constructs a field that carries a slice of integers.78func Int64s(key string, nums []int64) Field {79return Array(key, int64s(nums))80}8182// Int32s constructs a field that carries a slice of integers.83func Int32s(key string, nums []int32) Field {84return Array(key, int32s(nums))85}8687// Int16s constructs a field that carries a slice of integers.88func Int16s(key string, nums []int16) Field {89return Array(key, int16s(nums))90}9192// Int8s constructs a field that carries a slice of integers.93func Int8s(key string, nums []int8) Field {94return Array(key, int8s(nums))95}9697// Objects constructs a field with the given key, holding a list of the98// provided objects that can be marshaled by Zap.99//100// Note that these objects must implement zapcore.ObjectMarshaler directly.101// That is, if you're trying to marshal a []Request, the MarshalLogObject102// method must be declared on the Request type, not its pointer (*Request).103// If it's on the pointer, use ObjectValues.104//105// Given an object that implements MarshalLogObject on the value receiver, you106// can log a slice of those objects with Objects like so:107//108// type Author struct{ ... }109// func (a Author) MarshalLogObject(enc zapcore.ObjectEncoder) error110//111// var authors []Author = ...112// logger.Info("loading article", zap.Objects("authors", authors))113//114// Similarly, given a type that implements MarshalLogObject on its pointer115// receiver, you can log a slice of pointers to that object with Objects like116// so:117//118// type Request struct{ ... }119// func (r *Request) MarshalLogObject(enc zapcore.ObjectEncoder) error120//121// var requests []*Request = ...122// logger.Info("sending requests", zap.Objects("requests", requests))123//124// If instead, you have a slice of values of such an object, use the125// ObjectValues constructor.126//127// var requests []Request = ...128// logger.Info("sending requests", zap.ObjectValues("requests", requests))129func Objects[T zapcore.ObjectMarshaler](key string, values []T) Field {130return Array(key, objects[T](values))131}132133type objects[T zapcore.ObjectMarshaler] []T134135func (os objects[T]) MarshalLogArray(arr zapcore.ArrayEncoder) error {136for _, o := range os {137if err := arr.AppendObject(o); err != nil {138return err139}140}141return nil142}143144// ObjectMarshalerPtr is a constraint that specifies that the given type145// implements zapcore.ObjectMarshaler on a pointer receiver.146type ObjectMarshalerPtr[T any] interface {147*T148zapcore.ObjectMarshaler149}150151// ObjectValues constructs a field with the given key, holding a list of the152// provided objects, where pointers to these objects can be marshaled by Zap.153//154// Note that pointers to these objects must implement zapcore.ObjectMarshaler.155// That is, if you're trying to marshal a []Request, the MarshalLogObject156// method must be declared on the *Request type, not the value (Request).157// If it's on the value, use Objects.158//159// Given an object that implements MarshalLogObject on the pointer receiver,160// you can log a slice of those objects with ObjectValues like so:161//162// type Request struct{ ... }163// func (r *Request) MarshalLogObject(enc zapcore.ObjectEncoder) error164//165// var requests []Request = ...166// logger.Info("sending requests", zap.ObjectValues("requests", requests))167//168// If instead, you have a slice of pointers of such an object, use the Objects169// field constructor.170//171// var requests []*Request = ...172// logger.Info("sending requests", zap.Objects("requests", requests))173func ObjectValues[T any, P ObjectMarshalerPtr[T]](key string, values []T) Field {174return Array(key, objectValues[T, P](values))175}176177type objectValues[T any, P ObjectMarshalerPtr[T]] []T178179func (os objectValues[T, P]) MarshalLogArray(arr zapcore.ArrayEncoder) error {180for i := range os {181// It is necessary for us to explicitly reference the "P" type.182// We cannot simply pass "&os[i]" to AppendObject because its type183// is "*T", which the type system does not consider as184// implementing ObjectMarshaler.185// Only the type "P" satisfies ObjectMarshaler, which we have186// to convert "*T" to explicitly.187var p P = &os[i]188if err := arr.AppendObject(p); err != nil {189return err190}191}192return nil193}194195// Strings constructs a field that carries a slice of strings.196func Strings(key string, ss []string) Field {197return Array(key, stringArray(ss))198}199200// Stringers constructs a field with the given key, holding a list of the201// output provided by the value's String method202//203// Given an object that implements String on the value receiver, you204// can log a slice of those objects with Objects like so:205//206// type Request struct{ ... }207// func (a Request) String() string208//209// var requests []Request = ...210// logger.Info("sending requests", zap.Stringers("requests", requests))211//212// Note that these objects must implement fmt.Stringer directly.213// That is, if you're trying to marshal a []Request, the String method214// must be declared on the Request type, not its pointer (*Request).215func Stringers[T fmt.Stringer](key string, values []T) Field {216return Array(key, stringers[T](values))217}218219type stringers[T fmt.Stringer] []T220221func (os stringers[T]) MarshalLogArray(arr zapcore.ArrayEncoder) error {222for _, o := range os {223arr.AppendString(o.String())224}225return nil226}227228// Times constructs a field that carries a slice of time.Times.229func Times(key string, ts []time.Time) Field {230return Array(key, times(ts))231}232233// Uints constructs a field that carries a slice of unsigned integers.234func Uints(key string, nums []uint) Field {235return Array(key, uints(nums))236}237238// Uint64s constructs a field that carries a slice of unsigned integers.239func Uint64s(key string, nums []uint64) Field {240return Array(key, uint64s(nums))241}242243// Uint32s constructs a field that carries a slice of unsigned integers.244func Uint32s(key string, nums []uint32) Field {245return Array(key, uint32s(nums))246}247248// Uint16s constructs a field that carries a slice of unsigned integers.249func Uint16s(key string, nums []uint16) Field {250return Array(key, uint16s(nums))251}252253// Uint8s constructs a field that carries a slice of unsigned integers.254func Uint8s(key string, nums []uint8) Field {255return Array(key, uint8s(nums))256}257258// Uintptrs constructs a field that carries a slice of pointer addresses.259func Uintptrs(key string, us []uintptr) Field {260return Array(key, uintptrs(us))261}262263// Errors constructs a field that carries a slice of errors.264func Errors(key string, errs []error) Field {265return Array(key, errArray(errs))266}267268type bools []bool269270func (bs bools) MarshalLogArray(arr zapcore.ArrayEncoder) error {271for i := range bs {272arr.AppendBool(bs[i])273}274return nil275}276277type byteStringsArray [][]byte278279func (bss byteStringsArray) MarshalLogArray(arr zapcore.ArrayEncoder) error {280for i := range bss {281arr.AppendByteString(bss[i])282}283return nil284}285286type complex128s []complex128287288func (nums complex128s) MarshalLogArray(arr zapcore.ArrayEncoder) error {289for i := range nums {290arr.AppendComplex128(nums[i])291}292return nil293}294295type complex64s []complex64296297func (nums complex64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {298for i := range nums {299arr.AppendComplex64(nums[i])300}301return nil302}303304type durations []time.Duration305306func (ds durations) MarshalLogArray(arr zapcore.ArrayEncoder) error {307for i := range ds {308arr.AppendDuration(ds[i])309}310return nil311}312313type float64s []float64314315func (nums float64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {316for i := range nums {317arr.AppendFloat64(nums[i])318}319return nil320}321322type float32s []float32323324func (nums float32s) MarshalLogArray(arr zapcore.ArrayEncoder) error {325for i := range nums {326arr.AppendFloat32(nums[i])327}328return nil329}330331type ints []int332333func (nums ints) MarshalLogArray(arr zapcore.ArrayEncoder) error {334for i := range nums {335arr.AppendInt(nums[i])336}337return nil338}339340type int64s []int64341342func (nums int64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {343for i := range nums {344arr.AppendInt64(nums[i])345}346return nil347}348349type int32s []int32350351func (nums int32s) MarshalLogArray(arr zapcore.ArrayEncoder) error {352for i := range nums {353arr.AppendInt32(nums[i])354}355return nil356}357358type int16s []int16359360func (nums int16s) MarshalLogArray(arr zapcore.ArrayEncoder) error {361for i := range nums {362arr.AppendInt16(nums[i])363}364return nil365}366367type int8s []int8368369func (nums int8s) MarshalLogArray(arr zapcore.ArrayEncoder) error {370for i := range nums {371arr.AppendInt8(nums[i])372}373return nil374}375376type stringArray []string377378func (ss stringArray) MarshalLogArray(arr zapcore.ArrayEncoder) error {379for i := range ss {380arr.AppendString(ss[i])381}382return nil383}384385type times []time.Time386387func (ts times) MarshalLogArray(arr zapcore.ArrayEncoder) error {388for i := range ts {389arr.AppendTime(ts[i])390}391return nil392}393394type uints []uint395396func (nums uints) MarshalLogArray(arr zapcore.ArrayEncoder) error {397for i := range nums {398arr.AppendUint(nums[i])399}400return nil401}402403type uint64s []uint64404405func (nums uint64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {406for i := range nums {407arr.AppendUint64(nums[i])408}409return nil410}411412type uint32s []uint32413414func (nums uint32s) MarshalLogArray(arr zapcore.ArrayEncoder) error {415for i := range nums {416arr.AppendUint32(nums[i])417}418return nil419}420421type uint16s []uint16422423func (nums uint16s) MarshalLogArray(arr zapcore.ArrayEncoder) error {424for i := range nums {425arr.AppendUint16(nums[i])426}427return nil428}429430type uint8s []uint8431432func (nums uint8s) MarshalLogArray(arr zapcore.ArrayEncoder) error {433for i := range nums {434arr.AppendUint8(nums[i])435}436return nil437}438439type uintptrs []uintptr440441func (nums uintptrs) MarshalLogArray(arr zapcore.ArrayEncoder) error {442for i := range nums {443arr.AppendUintptr(nums[i])444}445return nil446}447448449