1 package log
2
3 import (
4 "fmt"
5 "math"
6 )
7
8 type fieldType int
9
10 const (
11 stringType fieldType = iota
12 boolType
13 intType
14 int32Type
15 uint32Type
16 int64Type
17 uint64Type
18 float32Type
19 float64Type
20 errorType
21 objectType
22 lazyLoggerType
23 noopType
24 )
25
26
27
28
29
30
31
32 type Field struct {
33 key string
34 fieldType fieldType
35 numericVal int64
36 stringVal string
37 interfaceVal interface{}
38 }
39
40
41 func String(key, val string) Field {
42 return Field{
43 key: key,
44 fieldType: stringType,
45 stringVal: val,
46 }
47 }
48
49
50 func Bool(key string, val bool) Field {
51 var numericVal int64
52 if val {
53 numericVal = 1
54 }
55 return Field{
56 key: key,
57 fieldType: boolType,
58 numericVal: numericVal,
59 }
60 }
61
62
63 func Int(key string, val int) Field {
64 return Field{
65 key: key,
66 fieldType: intType,
67 numericVal: int64(val),
68 }
69 }
70
71
72 func Int32(key string, val int32) Field {
73 return Field{
74 key: key,
75 fieldType: int32Type,
76 numericVal: int64(val),
77 }
78 }
79
80
81 func Int64(key string, val int64) Field {
82 return Field{
83 key: key,
84 fieldType: int64Type,
85 numericVal: val,
86 }
87 }
88
89
90 func Uint32(key string, val uint32) Field {
91 return Field{
92 key: key,
93 fieldType: uint32Type,
94 numericVal: int64(val),
95 }
96 }
97
98
99 func Uint64(key string, val uint64) Field {
100 return Field{
101 key: key,
102 fieldType: uint64Type,
103 numericVal: int64(val),
104 }
105 }
106
107
108 func Float32(key string, val float32) Field {
109 return Field{
110 key: key,
111 fieldType: float32Type,
112 numericVal: int64(math.Float32bits(val)),
113 }
114 }
115
116
117 func Float64(key string, val float64) Field {
118 return Field{
119 key: key,
120 fieldType: float64Type,
121 numericVal: int64(math.Float64bits(val)),
122 }
123 }
124
125
126 func Error(err error) Field {
127 return Field{
128 key: "error.object",
129 fieldType: errorType,
130 interfaceVal: err,
131 }
132 }
133
134
135
136
137
138 func Object(key string, obj interface{}) Field {
139 return Field{
140 key: key,
141 fieldType: objectType,
142 interfaceVal: obj,
143 }
144 }
145
146
147 func Event(val string) Field {
148 return String("event", val)
149 }
150
151
152 func Message(val string) Field {
153 return String("message", val)
154 }
155
156
157 type LazyLogger func(fv Encoder)
158
159
160
161
162 func Lazy(ll LazyLogger) Field {
163 return Field{
164 fieldType: lazyLoggerType,
165 interfaceVal: ll,
166 }
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182 func Noop() Field {
183 return Field{
184 fieldType: noopType,
185 }
186 }
187
188
189
190
191
192
193 type Encoder interface {
194 EmitString(key, value string)
195 EmitBool(key string, value bool)
196 EmitInt(key string, value int)
197 EmitInt32(key string, value int32)
198 EmitInt64(key string, value int64)
199 EmitUint32(key string, value uint32)
200 EmitUint64(key string, value uint64)
201 EmitFloat32(key string, value float32)
202 EmitFloat64(key string, value float64)
203 EmitObject(key string, value interface{})
204 EmitLazyLogger(value LazyLogger)
205 }
206
207
208
209 func (lf Field) Marshal(visitor Encoder) {
210 switch lf.fieldType {
211 case stringType:
212 visitor.EmitString(lf.key, lf.stringVal)
213 case boolType:
214 visitor.EmitBool(lf.key, lf.numericVal != 0)
215 case intType:
216 visitor.EmitInt(lf.key, int(lf.numericVal))
217 case int32Type:
218 visitor.EmitInt32(lf.key, int32(lf.numericVal))
219 case int64Type:
220 visitor.EmitInt64(lf.key, int64(lf.numericVal))
221 case uint32Type:
222 visitor.EmitUint32(lf.key, uint32(lf.numericVal))
223 case uint64Type:
224 visitor.EmitUint64(lf.key, uint64(lf.numericVal))
225 case float32Type:
226 visitor.EmitFloat32(lf.key, math.Float32frombits(uint32(lf.numericVal)))
227 case float64Type:
228 visitor.EmitFloat64(lf.key, math.Float64frombits(uint64(lf.numericVal)))
229 case errorType:
230 if err, ok := lf.interfaceVal.(error); ok {
231 visitor.EmitString(lf.key, err.Error())
232 } else {
233 visitor.EmitString(lf.key, "<nil>")
234 }
235 case objectType:
236 visitor.EmitObject(lf.key, lf.interfaceVal)
237 case lazyLoggerType:
238 visitor.EmitLazyLogger(lf.interfaceVal.(LazyLogger))
239 case noopType:
240
241 }
242 }
243
244
245 func (lf Field) Key() string {
246 return lf.key
247 }
248
249
250 func (lf Field) Value() interface{} {
251 switch lf.fieldType {
252 case stringType:
253 return lf.stringVal
254 case boolType:
255 return lf.numericVal != 0
256 case intType:
257 return int(lf.numericVal)
258 case int32Type:
259 return int32(lf.numericVal)
260 case int64Type:
261 return int64(lf.numericVal)
262 case uint32Type:
263 return uint32(lf.numericVal)
264 case uint64Type:
265 return uint64(lf.numericVal)
266 case float32Type:
267 return math.Float32frombits(uint32(lf.numericVal))
268 case float64Type:
269 return math.Float64frombits(uint64(lf.numericVal))
270 case errorType, objectType, lazyLoggerType:
271 return lf.interfaceVal
272 case noopType:
273 return nil
274 default:
275 return nil
276 }
277 }
278
279
280 func (lf Field) String() string {
281 return fmt.Sprint(lf.key, ":", lf.Value())
282 }
283
View as plain text