forked from nitishm/logger
-
Notifications
You must be signed in to change notification settings - Fork 0
/
logger.go
188 lines (160 loc) · 4.39 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
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
package logger
import (
"fmt"
"github.com/sasha-s/go-deadlock"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
)
// DefaultFieldsHook implements the logrus Hook interface
// We use it to add a set of default fields to all our logs
type DefaultFieldsHook struct {
defaults log.Fields
mu *deadlock.Mutex
}
// Levels implements the Levels methods for the logrus Hook interface
func (h *DefaultFieldsHook) Levels() []log.Level {
return log.AllLevels
}
// Fire implements the Levels methods for the logrus Hook interface
// This is where the defaults are added to the logrus Entry.Data map
func (h *DefaultFieldsHook) Fire(e *log.Entry) error {
h.mu.Lock()
defer h.mu.Unlock()
for k, v := range h.defaults {
e.Data[k] = v
}
return nil
}
// FieldHelper encompasses all field manipulation methods.
type FieldHelper interface {
Fields() log.Fields
AddField(key string, value interface{})
AddFields(fields log.Fields)
RemoveFieldsByKey(key ...string)
RemoveFields(fields log.Fields)
ResetFields()
}
// DefaultHelper encompasses all default manipulation methods.
type DefaultHelper interface {
Defaults() log.Fields
SetDefaults(defaults log.Fields)
}
// ErrorHelper encompasses all error helper methods.
type ErrorHelper interface {
WrapAndPrintWithError(err error, format string, args ...interface{}) error
PrintWithError(err error, format string, args ...interface{})
}
// Helper interface is a set of wrappers that the package
// provides over logrus.
type Helper interface {
FieldHelper
DefaultHelper
ErrorHelper
}
// Cloner interface provides a shallow copy method
type Cloner interface {
Clone() Logger
}
// Logger interface wraps the logrus interface and some additional helper functions
type Logger interface {
Logrus
Helper
Cloner
}
type logger struct {
*log.Entry
fields log.Fields
defaults log.Fields
mu *deadlock.RWMutex
}
// New returns a new instance of the logger struct
func New() *logger {
return &logger{
log.NewEntry(log.New()),
make(log.Fields),
make(log.Fields),
&deadlock.RWMutex{},
}
}
func (l *logger) updateFields() {
l.mu.Lock()
for k, v := range l.fields {
l.Entry.Data[k] = v
}
l.mu.Unlock()
}
// Defaults returns the set default fields map
func (l *logger) Defaults() log.Fields {
l.mu.RLock()
defer l.mu.RUnlock()
return l.defaults
}
// Fields returns the variable fields map
func (l *logger) Fields() log.Fields {
l.mu.RLock()
defer l.mu.RUnlock()
return l.fields
}
// SetDefaults sets the default fields
func (l *logger) SetDefaults(defaults log.Fields) {
l.defaults = defaults
l.Logger.AddHook(&DefaultFieldsHook{l.defaults, &deadlock.Mutex{}})
}
// AddField adds a single key value pair to the fields map
func (l *logger) AddField(key string, value interface{}) {
l.mu.Lock()
l.fields[key] = value
l.Data[key] = value
l.mu.Unlock()
}
// AddFields adds one or more kv pairs to the fields map
func (l *logger) AddFields(fields log.Fields) {
defer l.updateFields()
l.mu.Lock()
for k, v := range fields {
l.fields[k] = v
l.Data[k] = v
}
l.mu.Unlock()
}
// RemoveFieldsByKey removes one or more entries from the fields map by their key
func (l *logger) RemoveFieldsByKey(keys ...string) {
defer l.updateFields()
l.mu.Lock()
for _, k := range keys {
delete(l.fields, k)
delete(l.Data, k)
}
l.mu.Unlock()
}
// RemoveFieldsByKey removes one or more entries from the fields map using the same object used to set the kv pairs
func (l *logger) RemoveFields(fields log.Fields) {
defer l.updateFields()
l.mu.Lock()
for k, _ := range fields {
l.RemoveFieldsByKey(k)
}
l.mu.Unlock()
}
// ResetFields resets all the fields by clearing the fields map
func (l *logger) ResetFields() {
defer l.updateFields()
l.mu.Lock()
l.Data = make(map[string]interface{})
l.fields = make(map[string]interface{})
l.defaults = make(map[string]interface{})
l.SetDefaults(l.defaults)
l.mu.Unlock()
}
// WrapAndPrintWithError is a combination function that helps us log the error as well as wrap it with the custom error
// message
func (l *logger) WrapAndPrintWithError(err error, format string, args ...interface{}) error {
msg := fmt.Sprintf(format, args...)
err = errors.Wrap(err, msg)
l.WithError(err).Error(msg)
return err
}
// PrintWithError is a wrapper that helps reduce the verbosity of the WithError logrus method
func (l *logger) PrintWithError(err error, format string, args ...interface{}) {
l.WithError(err).Error(fmt.Sprintf(format, args...))
}