-
Notifications
You must be signed in to change notification settings - Fork 2
/
entry.go
241 lines (210 loc) · 6.51 KB
/
entry.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
package metrics
import (
"fmt"
"strings"
"time"
)
// level constants
const (
RedAlertLvl Level = iota // Immediately notify everyone by mail level, because this is bad
YellowAlertLvl // Immediately notify everyone but we can wait to tomorrow
ErrorLvl // Error occured with some code due to normal opperation or odd behaviour (not critical)
InfoLvl // Information for view about code operation (replaces Debug, Notice, Trace).
)
// Entry represent a giving record of data at a giving period of time.
type Entry struct {
ID string `json:"id"`
Function string `json:"function"`
File string `json:"file"`
Type string `json:"type"`
Line int `json:"line"`
Level Level `json:"level"`
Field Field `json:"fields"`
Time time.Time `json:"time"`
Message string `json:"message"`
Filter interface{} `json:"filter"`
Tags []string `json:"tags"`
Trace Trace `json:"trace"`
Timelapse []Timelapse `json:"timelapse"`
}
// Level defines a int type which represent the a giving level of entry for a giving entry.
type Level int
// GetLevel returns Level value for the giving string.
// It returns -1 if it does not know the level string.
func GetLevel(lvl string) Level {
switch strings.ToLower(lvl) {
case "redalert", "redalartlvl":
return RedAlertLvl
case "yellowalert", "yellowalertlvl":
return YellowAlertLvl
case "error", "errorlvl":
return ErrorLvl
case "info", "infolvl":
return InfoLvl
}
return -1
}
// String returns the string version of the Level.
func (l Level) String() string {
switch l {
case RedAlertLvl:
return "REDALERT"
case YellowAlertLvl:
return "YELLOWALERT"
case ErrorLvl:
return "ERROR"
case InfoLvl:
return "INFO"
}
return "UNKNOWN"
}
// Partial returns a new func(*Entry) which will always apply provided func(*Entry)
// to all provided Entry.
func Partial(mods ...func(*Entry)) func(*Entry) {
if len(mods) == 1 {
return mods[0]
}
return func(en *Entry) {
for _, mod := range mods {
mod(en)
}
}
}
// Apply runs all giving func(*Entry) functions provided on the provided Entry.
func Apply(en *Entry, mods ...func(*Entry)) {
for _, mod := range mods {
mod(en)
}
}
// Timelapse defines a message attached with a giving time value.
type Timelapse struct {
Message string `json:"message"`
Time time.Time `json:"time"`
Field Field `json:"fields"`
}
// WithTimelapse returns a Timelapse with associated field and message.
func WithTimelapse(message string, f Field) func(*Entry) {
return func(en *Entry) {
en.Timelapse = append(en.Timelapse, Timelapse{
Field: f,
Message: message,
Time: time.Now(),
})
}
}
// YellowAlert returns an Entry with the level set to YellowAlertLvl.
func YellowAlert(err error, message string, m ...interface{}) func(*Entry) {
return Partial(withMessageAt(4, YellowAlertLvl, message, m...), func(en *Entry) {
en.Field["error"] = err
})
}
// RedAlert returns an Entry with the level set to RedAlertLvl.
func RedAlert(err error, message string, m ...interface{}) func(*Entry) {
return Partial(withMessageAt(4, RedAlertLvl, message, m...), func(en *Entry) {
en.Field["error"] = err
})
}
// Errorf returns a entry where the message is the provided error.Error() value
// produced from the message and its provided values
// and the error is added as a key-value within the Entry fields.
func Errorf(message string, m ...interface{}) func(*Entry) {
err := fmt.Errorf(message, m...)
return Partial(withMessageAt(4, ErrorLvl, err.Error()), func(en *Entry) {
en.Field["error"] = err
})
}
// Error returns a entry where the message is the provided error.Error() value
// and the error is added as a key-value within the Entry fields.
func Error(err error) func(*Entry) {
return Partial(withMessageAt(4, ErrorLvl, err.Error()), func(en *Entry) {
en.Field["error"] = err
})
}
// Tags returns an Entry with the tags value set to ts.
func Tags(ts ...string) func(*Entry) {
return func(en *Entry) {
en.Tags = ts
}
}
// Type returns an Entry with the type value set to t.
func Type(t string) func(*Entry) {
return func(en *Entry) {
en.Type = t
}
}
// Info returns an Entry with the level set to Info.
func Info(message string, m ...interface{}) func(*Entry) {
return withMessageAt(4, InfoLvl, message, m...)
}
// Message returns a new Entry with the provided Level and message used.
func Message(message string, m ...interface{}) func(*Entry) {
function, file, line := getFunctionName(3)
return func(en *Entry) {
en.Message = fmt.Sprintf(message, m...)
en.Function, en.File, en.Line = function, file, line
}
}
// WithMessage returns a new Entry with the provided Level and message used.
func WithMessage(level Level, message string, m ...interface{}) func(*Entry) {
return withMessageAt(4, level, message, m...)
}
// withMessage returns a new Entry with the provided Level and message used.
func withMessageAt(depth int, level Level, message string, m ...interface{}) func(*Entry) {
function, file, line := getFunctionName(depth)
return func(e *Entry) {
e.Level = level
e.Field = make(Field)
e.Time = time.Now()
e.Function, e.File, e.Line = function, file, line
if len(m) == 0 {
e.Message = message
return
}
e.Message = fmt.Sprintf(message, m...)
}
}
// WithTrace returns itself after setting the giving trace value
// has the method trace for the giving Entry.
func WithTrace(t Trace) func(*Entry) {
function, file, line := getFunctionName(3)
return func(en *Entry) {
en.Trace = t
en.Function, en.File, en.Line = function, file, line
}
}
// WithFilter returns a Entry and set the Filter to the provided value.
func WithFilter(filter interface{}) func(*Entry) {
return func(en *Entry) {
en.Filter = filter
}
}
// WithID returns a Entry and set the ID to the provided value.
func WithID(id string) func(*Entry) {
function, file, line := getFunctionName(3)
return func(en *Entry) {
en.ID = id
en.Function, en.File, en.Line = function, file, line
}
}
// With returns a Entry set to the LogLevel of the previous and
// adds the giving key-value pair to the entry.
func With(key string, value interface{}) func(*Entry) {
return func(en *Entry) {
if en.Field == nil {
en.Field = make(Field)
}
en.Field[key] = value
}
}
// WithFields adds all field key-value pair into associated Entry
// returning the Entry.
func WithFields(f Field) func(*Entry) {
return func(en *Entry) {
if en.Field == nil {
en.Field = make(Field)
}
for k, v := range f {
en.Field[k] = v
}
}
}