field.go 7.0 KB

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