-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
logger.go
141 lines (123 loc) · 2.86 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
135
136
137
138
139
140
141
// Package logger provides logger configuration
package logger
import (
"context"
"os"
"sync"
"time"
)
var (
// Default logger
DefaultLogger Logger = NewLogger()
)
// Logger is a generic logging interface
type Logger interface {
// Init initializes options
Init(options ...Option) error
// The Logger options
Options() Options
// fields to be logged once
WithFields(fields map[string]interface{}) Record
// error to be logged once
WithError(err error) Record
// write args along with logger's default fields.
Log(level Level, args ...interface{})
// write formatted args along with logger's default fields.
Logf(level Level, format string, args ...interface{})
// String returns the name of logger
String() string
}
/**
* Default logger implementation
*/
type defaultLogger struct {
sync.RWMutex
opts Options
}
// Init(opts...) should only overwrite provided options
func (l *defaultLogger) Init(opts ...Option) error {
for _, o := range opts {
o(&l.opts)
}
return nil
}
func (n *defaultLogger) Options() Options {
return n.opts
}
func (l *defaultLogger) WithFields(fields map[string]interface{}) Record {
if len(l.opts.Fields) > 0 {
l.RLock()
fields = MergeMaps(l.opts.Fields, fields)
l.RUnlock()
} else if len(fields) == 0 {
fields = make(map[string]interface{}, 3)
}
return &defaultRecord{
opts: l.opts,
level: l.opts.Level,
fields: fields,
}
}
func (l *defaultLogger) WithError(err error) Record {
l.RLock()
fields := MergeMaps(l.opts.Fields, map[string]interface{}{"error": err.Error()})
l.RUnlock()
return &defaultRecord{
opts: l.opts,
level: l.opts.Level,
fields: fields,
}
}
func (l *defaultLogger) Log(level Level, args ...interface{}) {
if !l.opts.Level.Enabled(level) {
return
}
r := defaultRecord{
opts: l.opts,
level: l.opts.Level,
fields: l.opts.Fields,
}
r.Log(level, args...)
}
func (l *defaultLogger) Logf(level Level, format string, args ...interface{}) {
if !l.opts.Level.Enabled(level) {
return
}
r := defaultRecord{
opts: l.opts,
level: l.opts.Level,
fields: l.opts.Fields,
}
r.Logf(level, format, args...)
}
func (l *defaultLogger) String() string {
return "default"
}
// NewLogger builds a new logger based on options
func NewLogger(opts ...Option) Logger {
// Default options
options := Options{
Level: InfoLevel,
TimeFormat: time.RFC3339,
Fields: make(map[string]interface{}),
Out: os.Stderr,
Context: context.Background(),
}
l := &defaultLogger{opts: options}
_ = l.Init(opts...)
return l
}
// MergeMaps will overwriting duplicate keys, you should handle that, if there is a need
func MergeMaps(maps ...map[string]interface{}) map[string]interface{} {
var sum int
for _, m := range maps {
sum += len(m)
}
result := make(map[string]interface{}, sum)
for _, m := range maps {
for k, v := range m {
result[k] = v
}
}
return result
}