-
Notifications
You must be signed in to change notification settings - Fork 786
/
memberlist_logger.go
106 lines (96 loc) · 2.85 KB
/
memberlist_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
package memberlist
import (
"io"
"regexp"
"strings"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
)
// loggerAdapter wraps a Logger and allows it to be passed to the stdlib
// logger's SetOutput. It understand and parses output produced by memberlist
// library (esp. level). Timestamp from memberlist can be ignored (eg. util.Logger
// is set up to auto-include timestamp with every message already)
type loggerAdapter struct {
log.Logger
logTimestamp bool
}
// newMemberlistLoggerAdapter returns a new loggerAdapter, that can be passed
// memberlist.Config.LogOutput field.
func newMemberlistLoggerAdapter(logger log.Logger, logTimestamp bool) io.Writer {
a := loggerAdapter{
Logger: logger,
logTimestamp: logTimestamp,
}
return a
}
func (a loggerAdapter) Write(p []byte) (int, error) {
result := subexps(p)
keyvals := []interface{}{}
var timestamp string
if date, ok := result["date"]; ok && date != "" {
timestamp = date
}
if time, ok := result["time"]; ok && time != "" {
if timestamp != "" {
timestamp += " "
}
timestamp += time
}
if a.logTimestamp && timestamp != "" {
keyvals = append(keyvals, "ts", timestamp)
}
if file, ok := result["file"]; ok && file != "" {
keyvals = append(keyvals, "file", file)
}
if lvl, ok := result["level"]; ok {
lvl = strings.ToLower(lvl)
var lvlVal level.Value = nil
switch lvl {
case "debug":
lvlVal = level.DebugValue()
case "warn":
lvlVal = level.WarnValue()
case "info":
lvlVal = level.InfoValue()
case "err", "error":
lvlVal = level.ErrorValue()
}
if lvlVal != nil {
keyvals = append(keyvals, "level", lvlVal)
} else {
keyvals = append(keyvals, "level", lvl)
}
}
if msg, ok := result["msg"]; ok {
keyvals = append(keyvals, "msg", msg)
}
if err := a.Logger.Log(keyvals...); err != nil {
return 0, err
}
return len(p), nil
}
// 2019/10/01 12:05:06 [DEBUG] memberlist: Failed to join 127.0.0.1: dial tcp 127.0.0.1:8012: connect: connection refused
// 2019/10/01 12:07:34 /Users/test/go/pkg/mod/github.com/hashicorp/memberlist@v0.1.4/memberlist.go:245: [DEBUG] memberlist: Failed to join ::1: dial tcp [::1]:8012: connect: connection refused
const (
logRegexpDate = `(?P<date>[0-9]{4}/[0-9]{2}/[0-9]{2})?[ ]?`
logRegexpTime = `(?P<time>[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?)?[ ]?`
logRegexpFile = `(?P<file>[^: ]+?:[0-9]+)?(: )?`
logRegexpLevel = `(\[(?P<level>[A-Z]+)\] )?`
logRegexpMsg = `(?:memberlist: )?(?P<msg>.*)`
)
var (
logRegexp = regexp.MustCompile(logRegexpDate + logRegexpTime + logRegexpFile + logRegexpLevel + logRegexpMsg)
)
func subexps(line []byte) map[string]string {
m := logRegexp.FindSubmatch(line)
if len(m) < len(logRegexp.SubexpNames()) {
return map[string]string{}
}
result := map[string]string{}
for i, name := range logRegexp.SubexpNames() {
if name != "" {
result[name] = string(m[i])
}
}
return result
}