1 // Copyright (c) 2017 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 "go.uber.org/zap/internal/pool" 25 "go.uber.org/zap/zapcore" 26 ) 27 28 var _errArrayElemPool = pool.New(func() *errArrayElem { 29 return &errArrayElem{} 30 }) 31 32 // Error is shorthand for the common idiom NamedError("error", err). 33 func Error(err error) Field { 34 return NamedError("error", err) 35 } 36 37 // NamedError constructs a field that lazily stores err.Error() under the 38 // provided key. Errors which also implement fmt.Formatter (like those produced 39 // by github.com/pkg/errors) will also have their verbose representation stored 40 // under key+"Verbose". If passed a nil error, the field is a no-op. 41 // 42 // For the common case in which the key is simply "error", the Error function 43 // is shorter and less repetitive. 44 func NamedError(key string, err error) Field { 45 if err == nil { 46 return Skip() 47 } 48 return Field{Key: key, Type: zapcore.ErrorType, Interface: err} 49 } 50 51 type errArray []error 52 53 func (errs errArray) MarshalLogArray(arr zapcore.ArrayEncoder) error { 54 for i := range errs { 55 if errs[i] == nil { 56 continue 57 } 58 // To represent each error as an object with an "error" attribute and 59 // potentially an "errorVerbose" attribute, we need to wrap it in a 60 // type that implements LogObjectMarshaler. To prevent this from 61 // allocating, pool the wrapper type. 62 elem := _errArrayElemPool.Get() 63 elem.error = errs[i] 64 err := arr.AppendObject(elem) 65 elem.error = nil 66 _errArrayElemPool.Put(elem) 67 if err != nil { 68 return err 69 } 70 } 71 return nil 72 } 73 74 type errArrayElem struct { 75 error 76 } 77 78 func (e *errArrayElem) MarshalLogObject(enc zapcore.ObjectEncoder) error { 79 // Re-use the error field's logic, which supports non-standard error types. 80 Error(e.error).AddTo(enc) 81 return nil 82 } 83