Skip to content

Commit c6a867a

Browse files
Update logrus logger
1 parent 0b00a81 commit c6a867a

File tree

2 files changed

+197
-27
lines changed

2 files changed

+197
-27
lines changed

extension/logrus/logrus.go

Lines changed: 71 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package logrus
22

33
import (
4+
"sync/atomic"
5+
46
"github.com/hellofresh/goengine"
57
"github.com/sirupsen/logrus"
68
)
@@ -11,51 +13,96 @@ type wrapper struct {
1113

1214
// Wrap wraps a logrus.Logger
1315
func Wrap(logger *logrus.Logger) goengine.Logger {
14-
return wrapper{entry: logrus.NewEntry(logger)}
16+
return &wrapper{entry: logrus.NewEntry(logger)}
1517
}
1618

1719
// WrapEntry wraps a logrus.Entry
1820
func WrapEntry(entry *logrus.Entry) goengine.Logger {
19-
return wrapper{entry: entry}
21+
return &wrapper{entry: entry}
2022
}
2123

2224
// StandardLogger return a wrapped version of the logrus.StandardLogger()
2325
func StandardLogger() goengine.Logger {
2426
var origLogger = logrus.StandardLogger()
25-
return wrapper{entry: logrus.NewEntry(origLogger)}
27+
return &wrapper{entry: logrus.NewEntry(origLogger)}
28+
}
29+
30+
func (w wrapper) Error(msg string, fields func(goengine.LoggerEntry)) {
31+
if fields == nil {
32+
w.entry.Error(msg)
33+
return
34+
}
35+
36+
if w.enabled(logrus.ErrorLevel) {
37+
w.entry.WithFields(fieldsToMap(fields)).Error(msg)
38+
}
2639
}
2740

28-
// Error writes a log with log level error
29-
func (w wrapper) Error(msg string) {
30-
w.entry.Error(msg)
41+
func (w wrapper) Warn(msg string, fields func(goengine.LoggerEntry)) {
42+
if fields == nil {
43+
w.entry.Warn(msg)
44+
return
45+
}
46+
47+
if w.enabled(logrus.WarnLevel) {
48+
w.entry.WithFields(fieldsToMap(fields)).Warn(msg)
49+
}
3150
}
3251

33-
// Warn writes a log with log level warn
34-
func (w wrapper) Warn(msg string) {
35-
w.entry.Warn(msg)
52+
func (w wrapper) Info(msg string, fields func(goengine.LoggerEntry)) {
53+
if fields == nil {
54+
w.entry.Info(msg)
55+
return
56+
}
57+
58+
if w.enabled(logrus.InfoLevel) {
59+
w.entry.WithFields(fieldsToMap(fields)).Info(msg)
60+
}
3661
}
3762

38-
// Info writes a log with log level info
39-
func (w wrapper) Info(msg string) {
40-
w.entry.Warn(msg)
63+
func (w wrapper) Debug(msg string, fields func(goengine.LoggerEntry)) {
64+
if fields == nil {
65+
w.entry.Debug(msg)
66+
return
67+
}
68+
69+
if w.enabled(logrus.DebugLevel) {
70+
w.entry.WithFields(fieldsToMap(fields)).Debug(msg)
71+
}
4172
}
4273

43-
// Debug writes a log with log level debug
44-
func (w wrapper) Debug(msg string) {
45-
w.entry.Debug(msg)
74+
func (w *wrapper) WithFields(fields func(goengine.LoggerEntry)) goengine.Logger {
75+
if fields == nil {
76+
return w
77+
}
78+
79+
return &wrapper{entry: w.entry.WithFields(fieldsToMap(fields))}
80+
}
81+
82+
func (w wrapper) enabled(level logrus.Level) bool {
83+
return logrus.Level(atomic.LoadUint32((*uint32)(&w.entry.Logger.Level))) >= level
84+
}
85+
86+
func fieldsToMap(fields func(goengine.LoggerEntry)) logrus.Fields {
87+
e := entry{}
88+
fields(e)
89+
return logrus.Fields(e)
90+
}
91+
92+
type entry map[string]interface{}
93+
94+
func (e entry) Int(k string, v int) {
95+
e[k] = v
4696
}
4797

48-
// WithError Add an error as single field to the log entry
49-
func (w wrapper) WithError(err error) goengine.Logger {
50-
return wrapper{entry: w.entry.WithError(err)}
98+
func (e entry) String(k, v string) {
99+
e[k] = v
51100
}
52101

53-
// WithField Adds a field to the log entry
54-
func (w wrapper) WithField(key string, val interface{}) goengine.Logger {
55-
return wrapper{entry: w.entry.WithField(key, val)}
102+
func (e entry) Error(err error) {
103+
e["error"] = err
56104
}
57105

58-
//WithFields Adds a set of fields to the log entry
59-
func (w wrapper) WithFields(fields goengine.Fields) goengine.Logger {
60-
return wrapper{entry: w.entry.WithFields(logrus.Fields(fields))}
106+
func (e entry) Any(k string, v interface{}) {
107+
e[k] = v
61108
}

extension/logrus/logrus_test.go

Lines changed: 126 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,140 @@
33
package logrus_test
44

55
import (
6+
"errors"
67
"testing"
78

89
"github.com/hellofresh/goengine"
9-
10-
"github.com/hellofresh/goengine/extension/logrus"
10+
logrusExtension "github.com/hellofresh/goengine/extension/logrus"
11+
"github.com/sirupsen/logrus"
12+
"github.com/sirupsen/logrus/hooks/test"
13+
"github.com/stretchr/testify/assert"
1114
)
1215

16+
func TestWrap_LogEntry(t *testing.T) {
17+
logrusLogger, logObserver := test.NewNullLogger()
18+
logrusLogger.SetLevel(logrus.DebugLevel)
19+
logger := logrusExtension.Wrap(logrusLogger)
20+
21+
testCases := []struct {
22+
msg string
23+
fields func(goengine.LoggerEntry)
24+
25+
expectedMsg string
26+
expectedContext logrus.Fields
27+
}{
28+
{
29+
"test nil fields",
30+
nil,
31+
"test nil fields",
32+
logrus.Fields{},
33+
},
34+
{
35+
"test with fields",
36+
func(e goengine.LoggerEntry) {
37+
e.String("test", "a value")
38+
e.Int("normal_int", 99)
39+
e.Int64("int_64", 2)
40+
e.Error(errors.New("some error"))
41+
e.Any("obj", struct {
42+
test string
43+
}{test: "test property"})
44+
},
45+
"test with fields",
46+
logrus.Fields{
47+
"test": "a value",
48+
"normal_int": 99,
49+
"int_64": int64(2),
50+
"error": errors.New("some error"),
51+
"obj": struct {
52+
test string
53+
}{test: "test property"},
54+
},
55+
},
56+
}
57+
58+
for _, testCase := range testCases {
59+
t.Run(testCase.msg, func(t *testing.T) {
60+
defer logObserver.Reset()
61+
62+
logger.Error(testCase.msg, testCase.fields)
63+
logger.Warn(testCase.msg, testCase.fields)
64+
logger.Info(testCase.msg, testCase.fields)
65+
logger.Debug(testCase.msg, testCase.fields)
66+
67+
logs := logObserver.AllEntries()
68+
if !assert.Len(t, logs, 4) {
69+
return
70+
}
71+
72+
levelOrder := []logrus.Level{
73+
logrus.ErrorLevel,
74+
logrus.WarnLevel,
75+
logrus.InfoLevel,
76+
logrus.DebugLevel,
77+
}
78+
79+
for i, level := range levelOrder {
80+
assert.Equal(t, level, logs[i].Level)
81+
assert.Equal(t, testCase.expectedMsg, logs[i].Message)
82+
assert.Equal(t, testCase.expectedContext, logs[i].Data)
83+
}
84+
})
85+
}
86+
87+
t.Run("Do not log disabled levels", func(t *testing.T) {
88+
logrusLogger.SetLevel(logrus.InfoLevel)
89+
90+
logger.Debug("should not be logged", func(e goengine.LoggerEntry) {
91+
t.Error("fields should not be called")
92+
})
93+
94+
assert.Len(t, logObserver.AllEntries(), 0)
95+
})
96+
}
97+
98+
func TestWrapper_WithFields(t *testing.T) {
99+
logrusLogger, logObserver := test.NewNullLogger()
100+
logrusLogger.SetLevel(logrus.DebugLevel)
101+
logger := logrusExtension.Wrap(logrusLogger)
102+
103+
t.Run("With fields", func(t *testing.T) {
104+
loggerWithFields := logger.WithFields(func(e goengine.LoggerEntry) {
105+
e.String("with field", "check")
106+
e.String("val", "default")
107+
})
108+
109+
loggerWithFields.Debug("test with nil", nil)
110+
loggerWithFields.Debug("test with override", func(e goengine.LoggerEntry) {
111+
e.String("val", "override")
112+
})
113+
114+
logs := logObserver.AllEntries()
115+
if assert.Len(t, logs, 2) {
116+
assert.Equal(t, "test with nil", logs[0].Message)
117+
assert.Equal(t, logrus.Fields{
118+
"with field": "check",
119+
"val": "default",
120+
}, logs[0].Data)
121+
122+
assert.Equal(t, "test with override", logs[1].Message)
123+
assert.Equal(t, logrus.Fields{
124+
"with field": "check",
125+
"val": "override",
126+
}, logs[1].Data)
127+
}
128+
})
129+
130+
t.Run("With fields nil", func(t *testing.T) {
131+
loggerWithFields := logger.WithFields(nil)
132+
assert.Equal(t, logger, loggerWithFields)
133+
})
134+
}
135+
13136
func BenchmarkStandardLoggerEntry(b *testing.B) {
14137
b.ReportAllocs()
15138

16-
logger := logrus.StandardLogger()
139+
logger := logrusExtension.StandardLogger()
17140

18141
b.ResetTimer()
19142
for n := 0; n < b.N; n++ {

0 commit comments

Comments
 (0)