/
json.go
81 lines (74 loc) · 1.57 KB
/
json.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
package log
import (
"encoding/json"
"errors"
"fmt"
"io"
"reflect"
)
type jsonformatter struct {
out io.Writer
keynames *EventKeyNames // Names for basic event fields
}
// NewJSONFormatter creates a new formatting Handler writing log events as JSON to the supplied Writer.
func NewJSONFormatter(w io.Writer) *jsonformatter {
return &jsonformatter{keynames: defaultKeyNames, out: w}
}
func (l *jsonformatter) Log(e Event) error {
x := len(e.Data)
n := x/2 + 3
m := make(map[string]interface{}, n)
m[l.keynames.Lvl] = e.Lvl
m[l.keynames.Msg] = e.Msg
m[l.keynames.Time] = e.Time()
for i := 0; i < x; i += 2 {
k := e.Data[i]
var v interface{} = errors.New("MISSING")
if i+1 < len(e.Data) {
v = e.Data[i+1]
}
merge(m, k, v)
}
return json.NewEncoder(l.out).Encode(m)
}
func merge(dst map[string]interface{}, k, v interface{}) {
var key string
switch x := k.(type) {
case string:
key = x
case fmt.Stringer:
key = safeString(x)
default:
key = fmt.Sprint(x)
}
if x, ok := v.(error); ok {
v = safeError(x)
}
dst[key] = v
}
func safeString(str fmt.Stringer) (s string) {
defer func() {
if panicVal := recover(); panicVal != nil {
if v := reflect.ValueOf(str); v.Kind() == reflect.Ptr && v.IsNil() {
s = "NULL"
} else {
panic(panicVal)
}
}
}()
s = str.String()
return
}
func safeError(err error) (s interface{}) {
defer func() {
if panicVal := recover(); panicVal != nil {
if v := reflect.ValueOf(err); v.Kind() == reflect.Ptr && v.IsNil() {
s = nil
} else {
panic(panicVal)
}
}
}()
s = err.Error()
return
}