field.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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. package zapcore
  21. import (
  22. "bytes"
  23. "fmt"
  24. "math"
  25. "reflect"
  26. "time"
  27. )
  28. // A FieldType indicates which member of the Field union struct should be used
  29. // and how it should be serialized.
  30. type FieldType uint8
  31. const (
  32. // UnknownType is the default field type. Attempting to add it to an encoder will panic.
  33. UnknownType FieldType = iota
  34. // ArrayMarshalerType indicates that the field carries an ArrayMarshaler.
  35. ArrayMarshalerType
  36. // ObjectMarshalerType indicates that the field carries an ObjectMarshaler.
  37. ObjectMarshalerType
  38. // BinaryType indicates that the field carries an opaque binary blob.
  39. BinaryType
  40. // BoolType indicates that the field carries a bool.
  41. BoolType
  42. // ByteStringType indicates that the field carries UTF-8 encoded bytes.
  43. ByteStringType
  44. // Complex128Type indicates that the field carries a complex128.
  45. Complex128Type
  46. // Complex64Type indicates that the field carries a complex128.
  47. Complex64Type
  48. // DurationType indicates that the field carries a time.Duration.
  49. DurationType
  50. // Float64Type indicates that the field carries a float64.
  51. Float64Type
  52. // Float32Type indicates that the field carries a float32.
  53. Float32Type
  54. // Int64Type indicates that the field carries an int64.
  55. Int64Type
  56. // Int32Type indicates that the field carries an int32.
  57. Int32Type
  58. // Int16Type indicates that the field carries an int16.
  59. Int16Type
  60. // Int8Type indicates that the field carries an int8.
  61. Int8Type
  62. // StringType indicates that the field carries a string.
  63. StringType
  64. // TimeType indicates that the field carries a time.Time.
  65. TimeType
  66. // Uint64Type indicates that the field carries a uint64.
  67. Uint64Type
  68. // Uint32Type indicates that the field carries a uint32.
  69. Uint32Type
  70. // Uint16Type indicates that the field carries a uint16.
  71. Uint16Type
  72. // Uint8Type indicates that the field carries a uint8.
  73. Uint8Type
  74. // UintptrType indicates that the field carries a uintptr.
  75. UintptrType
  76. // ReflectType indicates that the field carries an interface{}, which should
  77. // be serialized using reflection.
  78. ReflectType
  79. // NamespaceType signals the beginning of an isolated namespace. All
  80. // subsequent fields should be added to the new namespace.
  81. NamespaceType
  82. // StringerType indicates that the field carries a fmt.Stringer.
  83. StringerType
  84. // ErrorType indicates that the field carries an error.
  85. ErrorType
  86. // SkipType indicates that the field is a no-op.
  87. SkipType
  88. )
  89. // A Field is a marshaling operation used to add a key-value pair to a logger's
  90. // context. Most fields are lazily marshaled, so it's inexpensive to add fields
  91. // to disabled debug-level log statements.
  92. type Field struct {
  93. Key string
  94. Type FieldType
  95. Integer int64
  96. String string
  97. Interface interface{}
  98. }
  99. // AddTo exports a field through the ObjectEncoder interface. It's primarily
  100. // useful to library authors, and shouldn't be necessary in most applications.
  101. func (f Field) AddTo(enc ObjectEncoder) {
  102. var err error
  103. switch f.Type {
  104. case ArrayMarshalerType:
  105. err = enc.AddArray(f.Key, f.Interface.(ArrayMarshaler))
  106. case ObjectMarshalerType:
  107. err = enc.AddObject(f.Key, f.Interface.(ObjectMarshaler))
  108. case BinaryType:
  109. enc.AddBinary(f.Key, f.Interface.([]byte))
  110. case BoolType:
  111. enc.AddBool(f.Key, f.Integer == 1)
  112. case ByteStringType:
  113. enc.AddByteString(f.Key, f.Interface.([]byte))
  114. case Complex128Type:
  115. enc.AddComplex128(f.Key, f.Interface.(complex128))
  116. case Complex64Type:
  117. enc.AddComplex64(f.Key, f.Interface.(complex64))
  118. case DurationType:
  119. enc.AddDuration(f.Key, time.Duration(f.Integer))
  120. case Float64Type:
  121. enc.AddFloat64(f.Key, math.Float64frombits(uint64(f.Integer)))
  122. case Float32Type:
  123. enc.AddFloat32(f.Key, math.Float32frombits(uint32(f.Integer)))
  124. case Int64Type:
  125. enc.AddInt64(f.Key, f.Integer)
  126. case Int32Type:
  127. enc.AddInt32(f.Key, int32(f.Integer))
  128. case Int16Type:
  129. enc.AddInt16(f.Key, int16(f.Integer))
  130. case Int8Type:
  131. enc.AddInt8(f.Key, int8(f.Integer))
  132. case StringType:
  133. enc.AddString(f.Key, f.String)
  134. case TimeType:
  135. if f.Interface != nil {
  136. enc.AddTime(f.Key, time.Unix(0, f.Integer).In(f.Interface.(*time.Location)))
  137. } else {
  138. // Fall back to UTC if location is nil.
  139. enc.AddTime(f.Key, time.Unix(0, f.Integer))
  140. }
  141. case Uint64Type:
  142. enc.AddUint64(f.Key, uint64(f.Integer))
  143. case Uint32Type:
  144. enc.AddUint32(f.Key, uint32(f.Integer))
  145. case Uint16Type:
  146. enc.AddUint16(f.Key, uint16(f.Integer))
  147. case Uint8Type:
  148. enc.AddUint8(f.Key, uint8(f.Integer))
  149. case UintptrType:
  150. enc.AddUintptr(f.Key, uintptr(f.Integer))
  151. case ReflectType:
  152. err = enc.AddReflected(f.Key, f.Interface)
  153. case NamespaceType:
  154. enc.OpenNamespace(f.Key)
  155. case StringerType:
  156. err = encodeStringer(f.Key, f.Interface, enc)
  157. case ErrorType:
  158. encodeError(f.Key, f.Interface.(error), enc)
  159. case SkipType:
  160. break
  161. default:
  162. panic(fmt.Sprintf("unknown field type: %v", f))
  163. }
  164. if err != nil {
  165. enc.AddString(fmt.Sprintf("%sError", f.Key), err.Error())
  166. }
  167. }
  168. // Equals returns whether two fields are equal. For non-primitive types such as
  169. // errors, marshalers, or reflect types, it uses reflect.DeepEqual.
  170. func (f Field) Equals(other Field) bool {
  171. if f.Type != other.Type {
  172. return false
  173. }
  174. if f.Key != other.Key {
  175. return false
  176. }
  177. switch f.Type {
  178. case BinaryType, ByteStringType:
  179. return bytes.Equal(f.Interface.([]byte), other.Interface.([]byte))
  180. case ArrayMarshalerType, ObjectMarshalerType, ErrorType, ReflectType:
  181. return reflect.DeepEqual(f.Interface, other.Interface)
  182. default:
  183. return f == other
  184. }
  185. }
  186. func addFields(enc ObjectEncoder, fields []Field) {
  187. for i := range fields {
  188. fields[i].AddTo(enc)
  189. }
  190. }
  191. func encodeStringer(key string, stringer interface{}, enc ObjectEncoder) (err error) {
  192. defer func() {
  193. if v := recover(); v != nil {
  194. err = fmt.Errorf("PANIC=%v", v)
  195. }
  196. }()
  197. enc.AddString(key, stringer.(fmt.Stringer).String())
  198. return
  199. }