/
logger.go
134 lines (118 loc) · 2.68 KB
/
logger.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
package logit
import (
"encoding/json"
"errors"
"fmt"
"io"
"time"
"github.com/araddon/dateparse"
"github.com/sirupsen/logrus"
)
// Levels represent configuration for default levels
type Levels struct {
Default logrus.Level
Error logrus.Level
}
type Logger struct {
Levels Levels
Handlers []Handler
Fields CFields
Defaults logrus.Fields
now func() time.Time
}
func (log *Logger) SetStream(stream io.Writer) {
for _, h := range log.Handlers {
h.SetStream(stream)
}
}
func (log Logger) SafeParse(line string) *logrus.Entry {
entry, err := log.Parse(line)
if err != nil {
err = fmt.Errorf("cannot parse entry: %v", err)
entry = logrus.NewEntry(nil)
entry.Level = log.Levels.Error
entry.Message = line
entry.Time = log.now()
entry.Data = copyFields(log.Defaults)
entry = entry.WithField("error", err.Error())
}
return entry
}
func (log Logger) Parse(line string) (*logrus.Entry, error) {
// If non-JSON passed, use it as message, set the default level
if line == "" || line[0] != '{' {
entry := logrus.NewEntry(nil)
entry.Level = log.Levels.Default
entry.Message = line
entry.Time = log.now()
entry.Data = copyFields(log.Defaults)
return entry, nil
}
e := logrus.NewEntry(nil)
e.Data = copyFields(log.Defaults)
err := json.Unmarshal([]byte(line), &e.Data)
if err != nil {
return nil, err
}
// extract message
msgRaw, ok := e.Data[log.Fields.Message]
if !ok {
return nil, errors.New("cannot find message field")
}
e.Message, ok = msgRaw.(string)
if !ok {
return nil, errors.New("message is not a string")
}
delete(e.Data, log.Fields.Message)
// extract level
lvlRaw, ok := e.Data[log.Fields.Level]
if !ok {
return nil, errors.New("cannot find level field")
}
lvlStr, ok := lvlRaw.(string)
if !ok {
return nil, errors.New("level is not a string")
}
e.Level, err = logrus.ParseLevel(lvlStr)
if err != nil {
return nil, err
}
delete(e.Data, log.Fields.Level)
// extract time
timeRaw, ok := e.Data[log.Fields.Time]
if ok {
timeStr, ok := timeRaw.(string)
if !ok {
return nil, errors.New("time is not a string")
}
e.Time, err = dateparse.ParseAny(timeStr)
if err != nil {
return nil, err
}
delete(e.Data, log.Fields.Time)
} else {
e.Time = log.now()
}
return e, nil
}
func (log Logger) Wait() {
for _, handler := range log.Handlers {
handler.Wait()
}
}
func (log Logger) Log(entry *logrus.Entry) error {
for _, handler := range log.Handlers {
err := handler.Log(entry)
if err != nil {
return fmt.Errorf("cannot write log entry: %v", err)
}
}
return nil
}
func copyFields(input logrus.Fields) logrus.Fields {
output := make(logrus.Fields)
for k, v := range input {
output[k] = v
}
return output
}