...

Source file src/go.uber.org/zap/array.go

Documentation: go.uber.org/zap

     1  // Copyright (c) 2016 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package zap
    22  
    23  import (
    24  	"fmt"
    25  	"time"
    26  
    27  	"go.uber.org/zap/zapcore"
    28  )
    29  
    30  // Array constructs a field with the given key and ArrayMarshaler. It provides
    31  // a flexible, but still type-safe and efficient, way to add array-like types
    32  // to the logging context. The struct's MarshalLogArray method is called lazily.
    33  func Array(key string, val zapcore.ArrayMarshaler) Field {
    34  	return Field{Key: key, Type: zapcore.ArrayMarshalerType, Interface: val}
    35  }
    36  
    37  // Bools constructs a field that carries a slice of bools.
    38  func Bools(key string, bs []bool) Field {
    39  	return Array(key, bools(bs))
    40  }
    41  
    42  // ByteStrings constructs a field that carries a slice of []byte, each of which
    43  // must be UTF-8 encoded text.
    44  func ByteStrings(key string, bss [][]byte) Field {
    45  	return Array(key, byteStringsArray(bss))
    46  }
    47  
    48  // Complex128s constructs a field that carries a slice of complex numbers.
    49  func Complex128s(key string, nums []complex128) Field {
    50  	return Array(key, complex128s(nums))
    51  }
    52  
    53  // Complex64s constructs a field that carries a slice of complex numbers.
    54  func Complex64s(key string, nums []complex64) Field {
    55  	return Array(key, complex64s(nums))
    56  }
    57  
    58  // Durations constructs a field that carries a slice of time.Durations.
    59  func Durations(key string, ds []time.Duration) Field {
    60  	return Array(key, durations(ds))
    61  }
    62  
    63  // Float64s constructs a field that carries a slice of floats.
    64  func Float64s(key string, nums []float64) Field {
    65  	return Array(key, float64s(nums))
    66  }
    67  
    68  // Float32s constructs a field that carries a slice of floats.
    69  func Float32s(key string, nums []float32) Field {
    70  	return Array(key, float32s(nums))
    71  }
    72  
    73  // Ints constructs a field that carries a slice of integers.
    74  func Ints(key string, nums []int) Field {
    75  	return Array(key, ints(nums))
    76  }
    77  
    78  // Int64s constructs a field that carries a slice of integers.
    79  func Int64s(key string, nums []int64) Field {
    80  	return Array(key, int64s(nums))
    81  }
    82  
    83  // Int32s constructs a field that carries a slice of integers.
    84  func Int32s(key string, nums []int32) Field {
    85  	return Array(key, int32s(nums))
    86  }
    87  
    88  // Int16s constructs a field that carries a slice of integers.
    89  func Int16s(key string, nums []int16) Field {
    90  	return Array(key, int16s(nums))
    91  }
    92  
    93  // Int8s constructs a field that carries a slice of integers.
    94  func Int8s(key string, nums []int8) Field {
    95  	return Array(key, int8s(nums))
    96  }
    97  
    98  // Objects constructs a field with the given key, holding a list of the
    99  // provided objects that can be marshaled by Zap.
   100  //
   101  // Note that these objects must implement zapcore.ObjectMarshaler directly.
   102  // That is, if you're trying to marshal a []Request, the MarshalLogObject
   103  // method must be declared on the Request type, not its pointer (*Request).
   104  // If it's on the pointer, use ObjectValues.
   105  //
   106  // Given an object that implements MarshalLogObject on the value receiver, you
   107  // can log a slice of those objects with Objects like so:
   108  //
   109  //	type Author struct{ ... }
   110  //	func (a Author) MarshalLogObject(enc zapcore.ObjectEncoder) error
   111  //
   112  //	var authors []Author = ...
   113  //	logger.Info("loading article", zap.Objects("authors", authors))
   114  //
   115  // Similarly, given a type that implements MarshalLogObject on its pointer
   116  // receiver, you can log a slice of pointers to that object with Objects like
   117  // so:
   118  //
   119  //	type Request struct{ ... }
   120  //	func (r *Request) MarshalLogObject(enc zapcore.ObjectEncoder) error
   121  //
   122  //	var requests []*Request = ...
   123  //	logger.Info("sending requests", zap.Objects("requests", requests))
   124  //
   125  // If instead, you have a slice of values of such an object, use the
   126  // ObjectValues constructor.
   127  //
   128  //	var requests []Request = ...
   129  //	logger.Info("sending requests", zap.ObjectValues("requests", requests))
   130  func Objects[T zapcore.ObjectMarshaler](key string, values []T) Field {
   131  	return Array(key, objects[T](values))
   132  }
   133  
   134  type objects[T zapcore.ObjectMarshaler] []T
   135  
   136  func (os objects[T]) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   137  	for _, o := range os {
   138  		if err := arr.AppendObject(o); err != nil {
   139  			return err
   140  		}
   141  	}
   142  	return nil
   143  }
   144  
   145  // ObjectMarshalerPtr is a constraint that specifies that the given type
   146  // implements zapcore.ObjectMarshaler on a pointer receiver.
   147  type ObjectMarshalerPtr[T any] interface {
   148  	*T
   149  	zapcore.ObjectMarshaler
   150  }
   151  
   152  // ObjectValues constructs a field with the given key, holding a list of the
   153  // provided objects, where pointers to these objects can be marshaled by Zap.
   154  //
   155  // Note that pointers to these objects must implement zapcore.ObjectMarshaler.
   156  // That is, if you're trying to marshal a []Request, the MarshalLogObject
   157  // method must be declared on the *Request type, not the value (Request).
   158  // If it's on the value, use Objects.
   159  //
   160  // Given an object that implements MarshalLogObject on the pointer receiver,
   161  // you can log a slice of those objects with ObjectValues like so:
   162  //
   163  //	type Request struct{ ... }
   164  //	func (r *Request) MarshalLogObject(enc zapcore.ObjectEncoder) error
   165  //
   166  //	var requests []Request = ...
   167  //	logger.Info("sending requests", zap.ObjectValues("requests", requests))
   168  //
   169  // If instead, you have a slice of pointers of such an object, use the Objects
   170  // field constructor.
   171  //
   172  //	var requests []*Request = ...
   173  //	logger.Info("sending requests", zap.Objects("requests", requests))
   174  func ObjectValues[T any, P ObjectMarshalerPtr[T]](key string, values []T) Field {
   175  	return Array(key, objectValues[T, P](values))
   176  }
   177  
   178  type objectValues[T any, P ObjectMarshalerPtr[T]] []T
   179  
   180  func (os objectValues[T, P]) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   181  	for i := range os {
   182  		// It is necessary for us to explicitly reference the "P" type.
   183  		// We cannot simply pass "&os[i]" to AppendObject because its type
   184  		// is "*T", which the type system does not consider as
   185  		// implementing ObjectMarshaler.
   186  		// Only the type "P" satisfies ObjectMarshaler, which we have
   187  		// to convert "*T" to explicitly.
   188  		var p P = &os[i]
   189  		if err := arr.AppendObject(p); err != nil {
   190  			return err
   191  		}
   192  	}
   193  	return nil
   194  }
   195  
   196  // Strings constructs a field that carries a slice of strings.
   197  func Strings(key string, ss []string) Field {
   198  	return Array(key, stringArray(ss))
   199  }
   200  
   201  // Stringers constructs a field with the given key, holding a list of the
   202  // output provided by the value's String method
   203  //
   204  // Given an object that implements String on the value receiver, you
   205  // can log a slice of those objects with Objects like so:
   206  //
   207  //	type Request struct{ ... }
   208  //	func (a Request) String() string
   209  //
   210  //	var requests []Request = ...
   211  //	logger.Info("sending requests", zap.Stringers("requests", requests))
   212  //
   213  // Note that these objects must implement fmt.Stringer directly.
   214  // That is, if you're trying to marshal a []Request, the String method
   215  // must be declared on the Request type, not its pointer (*Request).
   216  func Stringers[T fmt.Stringer](key string, values []T) Field {
   217  	return Array(key, stringers[T](values))
   218  }
   219  
   220  type stringers[T fmt.Stringer] []T
   221  
   222  func (os stringers[T]) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   223  	for _, o := range os {
   224  		arr.AppendString(o.String())
   225  	}
   226  	return nil
   227  }
   228  
   229  // Times constructs a field that carries a slice of time.Times.
   230  func Times(key string, ts []time.Time) Field {
   231  	return Array(key, times(ts))
   232  }
   233  
   234  // Uints constructs a field that carries a slice of unsigned integers.
   235  func Uints(key string, nums []uint) Field {
   236  	return Array(key, uints(nums))
   237  }
   238  
   239  // Uint64s constructs a field that carries a slice of unsigned integers.
   240  func Uint64s(key string, nums []uint64) Field {
   241  	return Array(key, uint64s(nums))
   242  }
   243  
   244  // Uint32s constructs a field that carries a slice of unsigned integers.
   245  func Uint32s(key string, nums []uint32) Field {
   246  	return Array(key, uint32s(nums))
   247  }
   248  
   249  // Uint16s constructs a field that carries a slice of unsigned integers.
   250  func Uint16s(key string, nums []uint16) Field {
   251  	return Array(key, uint16s(nums))
   252  }
   253  
   254  // Uint8s constructs a field that carries a slice of unsigned integers.
   255  func Uint8s(key string, nums []uint8) Field {
   256  	return Array(key, uint8s(nums))
   257  }
   258  
   259  // Uintptrs constructs a field that carries a slice of pointer addresses.
   260  func Uintptrs(key string, us []uintptr) Field {
   261  	return Array(key, uintptrs(us))
   262  }
   263  
   264  // Errors constructs a field that carries a slice of errors.
   265  func Errors(key string, errs []error) Field {
   266  	return Array(key, errArray(errs))
   267  }
   268  
   269  type bools []bool
   270  
   271  func (bs bools) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   272  	for i := range bs {
   273  		arr.AppendBool(bs[i])
   274  	}
   275  	return nil
   276  }
   277  
   278  type byteStringsArray [][]byte
   279  
   280  func (bss byteStringsArray) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   281  	for i := range bss {
   282  		arr.AppendByteString(bss[i])
   283  	}
   284  	return nil
   285  }
   286  
   287  type complex128s []complex128
   288  
   289  func (nums complex128s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   290  	for i := range nums {
   291  		arr.AppendComplex128(nums[i])
   292  	}
   293  	return nil
   294  }
   295  
   296  type complex64s []complex64
   297  
   298  func (nums complex64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   299  	for i := range nums {
   300  		arr.AppendComplex64(nums[i])
   301  	}
   302  	return nil
   303  }
   304  
   305  type durations []time.Duration
   306  
   307  func (ds durations) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   308  	for i := range ds {
   309  		arr.AppendDuration(ds[i])
   310  	}
   311  	return nil
   312  }
   313  
   314  type float64s []float64
   315  
   316  func (nums float64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   317  	for i := range nums {
   318  		arr.AppendFloat64(nums[i])
   319  	}
   320  	return nil
   321  }
   322  
   323  type float32s []float32
   324  
   325  func (nums float32s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   326  	for i := range nums {
   327  		arr.AppendFloat32(nums[i])
   328  	}
   329  	return nil
   330  }
   331  
   332  type ints []int
   333  
   334  func (nums ints) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   335  	for i := range nums {
   336  		arr.AppendInt(nums[i])
   337  	}
   338  	return nil
   339  }
   340  
   341  type int64s []int64
   342  
   343  func (nums int64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   344  	for i := range nums {
   345  		arr.AppendInt64(nums[i])
   346  	}
   347  	return nil
   348  }
   349  
   350  type int32s []int32
   351  
   352  func (nums int32s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   353  	for i := range nums {
   354  		arr.AppendInt32(nums[i])
   355  	}
   356  	return nil
   357  }
   358  
   359  type int16s []int16
   360  
   361  func (nums int16s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   362  	for i := range nums {
   363  		arr.AppendInt16(nums[i])
   364  	}
   365  	return nil
   366  }
   367  
   368  type int8s []int8
   369  
   370  func (nums int8s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   371  	for i := range nums {
   372  		arr.AppendInt8(nums[i])
   373  	}
   374  	return nil
   375  }
   376  
   377  type stringArray []string
   378  
   379  func (ss stringArray) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   380  	for i := range ss {
   381  		arr.AppendString(ss[i])
   382  	}
   383  	return nil
   384  }
   385  
   386  type times []time.Time
   387  
   388  func (ts times) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   389  	for i := range ts {
   390  		arr.AppendTime(ts[i])
   391  	}
   392  	return nil
   393  }
   394  
   395  type uints []uint
   396  
   397  func (nums uints) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   398  	for i := range nums {
   399  		arr.AppendUint(nums[i])
   400  	}
   401  	return nil
   402  }
   403  
   404  type uint64s []uint64
   405  
   406  func (nums uint64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   407  	for i := range nums {
   408  		arr.AppendUint64(nums[i])
   409  	}
   410  	return nil
   411  }
   412  
   413  type uint32s []uint32
   414  
   415  func (nums uint32s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   416  	for i := range nums {
   417  		arr.AppendUint32(nums[i])
   418  	}
   419  	return nil
   420  }
   421  
   422  type uint16s []uint16
   423  
   424  func (nums uint16s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   425  	for i := range nums {
   426  		arr.AppendUint16(nums[i])
   427  	}
   428  	return nil
   429  }
   430  
   431  type uint8s []uint8
   432  
   433  func (nums uint8s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   434  	for i := range nums {
   435  		arr.AppendUint8(nums[i])
   436  	}
   437  	return nil
   438  }
   439  
   440  type uintptrs []uintptr
   441  
   442  func (nums uintptrs) MarshalLogArray(arr zapcore.ArrayEncoder) error {
   443  	for i := range nums {
   444  		arr.AppendUintptr(nums[i])
   445  	}
   446  	return nil
   447  }
   448  

View as plain text