1 // Copyright (c) 2016 Uber Technologies, Inc.
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:
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
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
31 // A FieldType indicates which member of the Field union struct should be used
32 // and how it should be serialized.
36 // UnknownType is the default field type. Attempting to add it to an encoder will panic.
37 UnknownType FieldType = iota
38 // ArrayMarshalerType indicates that the field carries an ArrayMarshaler.
40 // ObjectMarshalerType indicates that the field carries an ObjectMarshaler.
42 // BinaryType indicates that the field carries an opaque binary blob.
44 // BoolType indicates that the field carries a bool.
46 // ByteStringType indicates that the field carries UTF-8 encoded bytes.
48 // Complex128Type indicates that the field carries a complex128.
50 // Complex64Type indicates that the field carries a complex128.
52 // DurationType indicates that the field carries a time.Duration.
54 // Float64Type indicates that the field carries a float64.
56 // Float32Type indicates that the field carries a float32.
58 // Int64Type indicates that the field carries an int64.
60 // Int32Type indicates that the field carries an int32.
62 // Int16Type indicates that the field carries an int16.
64 // Int8Type indicates that the field carries an int8.
66 // StringType indicates that the field carries a string.
68 // TimeType indicates that the field carries a time.Time.
70 // Uint64Type indicates that the field carries a uint64.
72 // Uint32Type indicates that the field carries a uint32.
74 // Uint16Type indicates that the field carries a uint16.
76 // Uint8Type indicates that the field carries a uint8.
78 // UintptrType indicates that the field carries a uintptr.
80 // ReflectType indicates that the field carries an interface{}, which should
81 // be serialized using reflection.
83 // NamespaceType signals the beginning of an isolated namespace. All
84 // subsequent fields should be added to the new namespace.
86 // StringerType indicates that the field carries a fmt.Stringer.
88 // ErrorType indicates that the field carries an error.
90 // SkipType indicates that the field is a no-op.
94 // A Field is a marshaling operation used to add a key-value pair to a logger's
95 // context. Most fields are lazily marshaled, so it's inexpensive to add fields
96 // to disabled debug-level log statements.
102 Interface interface{}
105 // AddTo exports a field through the ObjectEncoder interface. It's primarily
106 // useful to library authors, and shouldn't be necessary in most applications.
107 func (f Field) AddTo(enc ObjectEncoder) {
111 case ArrayMarshalerType:
112 err = enc.AddArray(f.Key, f.Interface.(ArrayMarshaler))
113 case ObjectMarshalerType:
114 err = enc.AddObject(f.Key, f.Interface.(ObjectMarshaler))
116 enc.AddBinary(f.Key, f.Interface.([]byte))
118 enc.AddBool(f.Key, f.Integer == 1)
120 enc.AddByteString(f.Key, f.Interface.([]byte))
122 enc.AddComplex128(f.Key, f.Interface.(complex128))
124 enc.AddComplex64(f.Key, f.Interface.(complex64))
126 enc.AddDuration(f.Key, time.Duration(f.Integer))
128 enc.AddFloat64(f.Key, math.Float64frombits(uint64(f.Integer)))
130 enc.AddFloat32(f.Key, math.Float32frombits(uint32(f.Integer)))
132 enc.AddInt64(f.Key, f.Integer)
134 enc.AddInt32(f.Key, int32(f.Integer))
136 enc.AddInt16(f.Key, int16(f.Integer))
138 enc.AddInt8(f.Key, int8(f.Integer))
140 enc.AddString(f.Key, f.String)
142 if f.Interface != nil {
143 enc.AddTime(f.Key, time.Unix(0, f.Integer).In(f.Interface.(*time.Location)))
145 // Fall back to UTC if location is nil.
146 enc.AddTime(f.Key, time.Unix(0, f.Integer))
149 enc.AddUint64(f.Key, uint64(f.Integer))
151 enc.AddUint32(f.Key, uint32(f.Integer))
153 enc.AddUint16(f.Key, uint16(f.Integer))
155 enc.AddUint8(f.Key, uint8(f.Integer))
157 enc.AddUintptr(f.Key, uintptr(f.Integer))
159 err = enc.AddReflected(f.Key, f.Interface)
161 enc.OpenNamespace(f.Key)
163 enc.AddString(f.Key, f.Interface.(fmt.Stringer).String())
165 encodeError(f.Key, f.Interface.(error), enc)
169 panic(fmt.Sprintf("unknown field type: %v", f))
173 enc.AddString(fmt.Sprintf("%sError", f.Key), err.Error())
177 // Equals returns whether two fields are equal. For non-primitive types such as
178 // errors, marshalers, or reflect types, it uses reflect.DeepEqual.
179 func (f Field) Equals(other Field) bool {
180 if f.Type != other.Type {
183 if f.Key != other.Key {
188 case BinaryType, ByteStringType:
189 return bytes.Equal(f.Interface.([]byte), other.Interface.([]byte))
190 case ArrayMarshalerType, ObjectMarshalerType, ErrorType, ReflectType:
191 return reflect.DeepEqual(f.Interface, other.Interface)
197 func addFields(enc ObjectEncoder, fields []Field) {
198 for i := range fields {