-
Notifications
You must be signed in to change notification settings - Fork 3
/
field.go
311 lines (279 loc) · 8.04 KB
/
field.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
package logger
import (
"encoding/json"
"fmt"
"github.com/valyala/bytebufferpool"
"strconv"
"time"
)
// FieldType represents the type of a logger context field
type FieldType uint8
// list of available field types
const (
// UnknownType is the default field type.
UnknownType FieldType = iota
// SkipType indicates that the field is a no-op.
SkipType
BoolType
Int8Type
Int16Type
Int32Type
Int64Type
Uint8Type
Uint16Type
Uint32Type
Uint64Type
UintptrType
Float32Type
Float64Type
Complex64Type
Complex128Type
StringType
BinaryType
ByteStringType
ErrorType
TimeType
DurationType
StringerType
// ReflectType indicates that the field carries an interface{}, which should be serialized using reflection.
ReflectType
// @TODO ArrayMarshallerType
// @TODO ObjectMarshallerType
)
// Field represents a contextual information
// this data was carry by Context struct
type Field struct {
Name string
Type FieldType
Value interface{}
}
// String will return Field as string
func (f *Field) String() string {
if f.Value == nil {
return "<nil>"
}
switch f.Type {
case SkipType:
return "<skipped>"
case BoolType:
if f.Value.(bool) {
return "true"
}
return "false"
case Int8Type:
return strconv.FormatInt(int64(f.Value.(int8)), 10)
case Int16Type:
return strconv.FormatInt(int64(f.Value.(int16)), 10)
case Int32Type:
return strconv.FormatInt(int64(f.Value.(int32)), 10)
case Int64Type:
return strconv.FormatInt(f.Value.(int64), 10)
case Uint8Type:
return strconv.FormatUint(uint64(f.Value.(uint8)), 10)
case Uint16Type:
return strconv.FormatUint(uint64(f.Value.(uint16)), 10)
case Uint32Type:
return strconv.FormatUint(uint64(f.Value.(uint32)), 10)
case Uint64Type:
return strconv.FormatUint(f.Value.(uint64), 10)
case UintptrType:
return strconv.FormatUint(uint64(f.Value.(uintptr)), 10)
case Float32Type:
return strconv.FormatFloat(float64(f.Value.(float32)), 'g', 10, 64)
case Float64Type:
return strconv.FormatFloat(f.Value.(float64), 'g', 10, 64)
case Complex64Type:
return fmt.Sprintf("%v", f.Value.(complex64))
case Complex128Type:
return fmt.Sprintf("%v", f.Value.(complex128))
case StringType:
return f.Value.(string)
case BinaryType:
return string(f.Value.([]byte)[:])
case ByteStringType:
return string(f.Value.([]byte)[:])
case ErrorType:
return f.Value.(error).Error()
case TimeType:
return f.Value.(time.Time).String()
case DurationType:
return f.Value.(time.Duration).String()
case StringerType:
return f.Value.(fmt.Stringer).String()
default:
return fmt.Sprintf("%v", f.Value)
}
}
// MarshalJSON was called by json.Marshal(field)
// json Marshaller interface
func (f *Field) MarshalJSON() ([]byte, error) {
if marshallable, ok := f.Value.(json.Marshaler); ok {
return marshallable.MarshalJSON()
}
if f.Type == ErrorType && f.Value == nil {
return []byte("null"), nil
}
switch f.Type {
case BoolType, Int8Type, Int16Type, Int32Type, Int64Type, Uint8Type, Uint16Type, Uint32Type, Uint64Type, UintptrType, Float32Type, Float64Type:
return []byte(f.String()), nil
case SkipType, Complex64Type, Complex128Type, StringType, BinaryType, ByteStringType, ErrorType, TimeType, DurationType, StringerType:
return strconv.AppendQuote([]byte{}, f.String()), nil
default:
return json.Marshal(f.Value)
}
}
// GoString was called by fmt.Printf("%#v", Fields)
// fmt GoStringer interface
func (f *Field) GoString() string {
byteBuffer := bytebufferpool.Get()
defer bytebufferpool.Put(byteBuffer)
byteBuffer.WriteString("logger.Field{Name: ")
byteBuffer.WriteString(f.Name)
byteBuffer.WriteString(", Value: ")
byteBuffer.WriteString(f.String())
byteBuffer.WriteString(", Type: ")
byteBuffer.WriteString(strconv.FormatUint(uint64(f.Type), 10))
byteBuffer.WriteString("}")
return byteBuffer.String()
}
// Skip will create Skip Field
func Skip(name string, value string) Field {
return Field{Name: name, Type: SkipType, Value: value}
}
// Bool will create Bool Field
func Bool(name string, value bool) Field {
return Field{Name: name, Type: BoolType, Value: value}
}
// Int8 will create Int8 Field
func Int8(name string, value int8) Field {
return Field{Name: name, Type: Int8Type, Value: value}
}
// Int16 will create Int16 Field
func Int16(name string, value int16) Field {
return Field{Name: name, Type: Int16Type, Value: value}
}
// Int32 will create Int32 Field
func Int32(name string, value int32) Field {
return Field{Name: name, Type: Int32Type, Value: value}
}
// Int64 will create Int64 Field
func Int64(name string, value int64) Field {
return Field{Name: name, Type: Int64Type, Value: value}
}
// Uint8 will create Uint8 Field
func Uint8(name string, value uint8) Field {
return Field{Name: name, Type: Uint8Type, Value: value}
}
// Uint16 will create Uint16 Field
func Uint16(name string, value uint16) Field {
return Field{Name: name, Type: Uint16Type, Value: value}
}
// Uint32 will create Uint32 Field
func Uint32(name string, value uint32) Field {
return Field{Name: name, Type: Uint32Type, Value: value}
}
// Uint64 will create Uint64 Field
func Uint64(name string, value uint64) Field {
return Field{Name: name, Type: Uint64Type, Value: value}
}
// Uintptr will create Uintptr Field
func Uintptr(name string, value uintptr) Field {
return Field{Name: name, Type: UintptrType, Value: value}
}
// Float32 will create Float32 Field
func Float32(name string, value float32) Field {
return Field{Name: name, Type: Float32Type, Value: value}
}
// Float64 will create Float64 Field
func Float64(name string, value float64) Field {
return Field{Name: name, Type: Float64Type, Value: value}
}
// Complex64 will create Complex64 Field
func Complex64(name string, value complex64) Field {
return Field{Name: name, Type: Complex64Type, Value: value}
}
// Complex128 will create Complex128 Field
func Complex128(name string, value complex128) Field {
return Field{Name: name, Type: Complex128Type, Value: value}
}
// String will create String Field
func String(name string, value string) Field {
return Field{Name: name, Type: StringType, Value: value}
}
// Binary will create Binary Field
func Binary(name string, value []byte) Field {
return Field{Name: name, Type: BinaryType, Value: value}
}
// ByteString will create ByteString Field
func ByteString(name string, value []byte) Field {
return Field{Name: name, Type: ByteStringType, Value: value}
}
// Error will create Error Field
func Error(name string, value error) Field {
return Field{Name: name, Type: ErrorType, Value: value}
}
// Stringer will create Stringer Field
func Stringer(name string, value fmt.Stringer) Field {
return Field{Name: name, Type: StringerType, Value: value}
}
// Time will create Time Field
func Time(name string, value time.Time) Field {
return Field{Name: name, Type: TimeType, Value: value}
}
// Duration will create Duration Field
func Duration(name string, value time.Duration) Field {
return Field{Name: name, Type: DurationType, Value: value}
}
// Reflect will create Reflect Field
func Reflect(name string, value interface{}) Field {
return Field{Name: name, Type: ReflectType, Value: value}
}
// Any will guess and create Field for given value
func Any(name string, value interface{}) Field {
switch val := value.(type) {
case bool:
return Bool(name, val)
case int:
return Int64(name, int64(val))
case int8:
return Int8(name, val)
case int16:
return Int16(name, val)
case int32:
return Int32(name, val)
case int64:
return Int64(name, val)
case uint8:
return Uint8(name, val)
case uint16:
return Uint16(name, val)
case uint32:
return Uint32(name, val)
case uint64:
return Uint64(name, val)
case uintptr:
return Uintptr(name, val)
case float32:
return Float32(name, val)
case float64:
return Float64(name, val)
case complex64:
return Complex64(name, val)
case complex128:
return Complex128(name, val)
case string:
return String(name, val)
case []byte:
return Binary(name, val)
case error:
return Error(name, val)
case time.Time:
return Time(name, val)
case time.Duration:
return Duration(name, val)
case fmt.Stringer:
return Stringer(name, val)
default:
return Reflect(name, val)
}
}