github.com/Laisky/zap@v1.27.0/array.go (about) 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 "github.com/Laisky/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 }