Parcourir la source

Add zerolog implementation

tags/v2.0.0-rc1
9seconds il y a 5 ans
Parent
révision
ab585fd699
2 fichiers modifiés avec 231 ajouts et 0 suppressions
  1. 115
    0
      logger/zerolog.go
  2. 116
    0
      logger/zerolog_test.go

+ 115
- 0
logger/zerolog.go Voir le fichier

@@ -0,0 +1,115 @@
1
+package logger
2
+
3
+import (
4
+	"github.com/9seconds/mtg/v2/mtglib"
5
+	"github.com/rs/zerolog"
6
+)
7
+
8
+const loggerFieldName = "logger"
9
+
10
+type zeroLogContextVarType uint8
11
+
12
+const (
13
+	zeroLogContextVarTypeUnknown zeroLogContextVarType = iota
14
+	zeroLogContextVarTypeStr
15
+	zeroLogContextVarTypeInt
16
+)
17
+
18
+type zeroLogContext struct {
19
+	name string
20
+	log  *zerolog.Logger
21
+
22
+	ctxVarType zeroLogContextVarType
23
+	ctxVarName string
24
+	ctxVarStr  string
25
+	ctxVarInt  int
26
+
27
+	parent *zeroLogContext
28
+}
29
+
30
+func (z *zeroLogContext) Named(name string) mtglib.Logger {
31
+	loggerName := z.name
32
+	if loggerName == "" {
33
+		loggerName = name
34
+	} else {
35
+		loggerName += "." + name
36
+	}
37
+
38
+	return &zeroLogContext{
39
+		name:   loggerName,
40
+		log:    z.log,
41
+		parent: z,
42
+	}
43
+}
44
+
45
+func (z *zeroLogContext) BindInt(name string, value int) mtglib.Logger {
46
+	return &zeroLogContext{
47
+		name:       z.name,
48
+		log:        z.log,
49
+		ctxVarType: zeroLogContextVarTypeInt,
50
+		ctxVarInt:  value,
51
+		ctxVarName: name,
52
+		parent:     z,
53
+	}
54
+}
55
+
56
+func (z *zeroLogContext) BindStr(name, value string) mtglib.Logger {
57
+	return &zeroLogContext{
58
+		name:       z.name,
59
+		log:        z.log,
60
+		ctxVarType: zeroLogContextVarTypeStr,
61
+		ctxVarStr:  value,
62
+		ctxVarName: name,
63
+		parent:     z,
64
+	}
65
+}
66
+
67
+func (z *zeroLogContext) Info(msg string) {
68
+	z.InfoError(msg, nil)
69
+}
70
+
71
+func (z *zeroLogContext) Warning(msg string) {
72
+	z.WarningError(msg, nil)
73
+}
74
+
75
+func (z *zeroLogContext) Debug(msg string) {
76
+	z.DebugError(msg, nil)
77
+}
78
+
79
+func (z *zeroLogContext) InfoError(msg string, err error) {
80
+	z.emitLog(z.log.Info(), msg, err)
81
+}
82
+
83
+func (z *zeroLogContext) WarningError(msg string, err error) {
84
+	z.emitLog(z.log.Warn(), msg, err)
85
+}
86
+
87
+func (z *zeroLogContext) DebugError(msg string, err error) {
88
+	z.emitLog(z.log.Debug(), msg, err)
89
+}
90
+
91
+func (z *zeroLogContext) emitLog(evt *zerolog.Event, msg string, err error) {
92
+	z.attachCtx(evt)
93
+
94
+	for current := z.parent; current != nil; current = current.parent {
95
+		current.attachCtx(evt)
96
+	}
97
+
98
+	evt.Str(loggerFieldName, z.name).Err(err).Msg(msg)
99
+}
100
+
101
+func (z *zeroLogContext) attachCtx(evt *zerolog.Event) {
102
+	switch z.ctxVarType {
103
+	case zeroLogContextVarTypeStr:
104
+		evt.Str(z.ctxVarName, z.ctxVarStr)
105
+	case zeroLogContextVarTypeInt:
106
+		evt.Int(z.ctxVarName, z.ctxVarInt)
107
+	case zeroLogContextVarTypeUnknown:
108
+	}
109
+}
110
+
111
+func NewZeroLogger(log zerolog.Logger) mtglib.Logger {
112
+	return &zeroLogContext{
113
+		log: &log,
114
+	}
115
+}

+ 116
- 0
logger/zerolog_test.go Voir le fichier

@@ -0,0 +1,116 @@
1
+package logger_test
2
+
3
+import (
4
+	"bytes"
5
+	"encoding/json"
6
+	"io"
7
+	"strings"
8
+	"testing"
9
+	"time"
10
+
11
+	"github.com/9seconds/mtg/v2/logger"
12
+	"github.com/9seconds/mtg/v2/mtglib"
13
+	"github.com/rs/zerolog"
14
+	"github.com/stretchr/testify/assert"
15
+	"github.com/stretchr/testify/suite"
16
+)
17
+
18
+type zeroLoggerLogMessage struct {
19
+	Timestamp int64  `json:"timestamp"`
20
+	Level     string `json:"level"`
21
+	StrParam  string `json:"strparam"`
22
+	IntParam  int    `json:"intparam"`
23
+	Logger    string `json:"logger"`
24
+	Error     string `json:"error"`
25
+	Message   string `json:"message"`
26
+}
27
+
28
+type ZeroLoggerTestSuite struct {
29
+	suite.Suite
30
+}
31
+
32
+func (suite *ZeroLoggerTestSuite) SetupSuite() {
33
+	zerolog.SetGlobalLevel(zerolog.TraceLevel)
34
+
35
+	zerolog.TimeFieldFormat = zerolog.TimeFormatUnixMs
36
+	zerolog.TimestampFieldName = "timestamp"
37
+	zerolog.LevelFieldName = "level"
38
+}
39
+
40
+func (suite *ZeroLoggerTestSuite) TestLog() {
41
+	testData := map[string]func(mtglib.Logger){
42
+		"info":        func(l mtglib.Logger) { l.Info("hello") },
43
+		"warn":        func(l mtglib.Logger) { l.Warning("hello") },
44
+		"debug":       func(l mtglib.Logger) { l.Debug("hello") },
45
+		"info-error":  func(l mtglib.Logger) { l.InfoError("hello", io.EOF) },
46
+		"warn-error":  func(l mtglib.Logger) { l.WarningError("hello", io.EOF) },
47
+		"debug-error": func(l mtglib.Logger) { l.DebugError("hello", io.EOF) },
48
+	}
49
+
50
+	for k, v := range testData {
51
+		name := k
52
+		callback := v
53
+		level := strings.TrimSuffix(name, "-error")
54
+
55
+		suite.T().Run(name, func(t *testing.T) {
56
+			buf := &bytes.Buffer{}
57
+			log := logger.NewZeroLogger(zerolog.New(buf).With().Timestamp().Logger())
58
+
59
+			callback(log.Named("name").BindInt("intparam", 1).BindStr("strparam", name))
60
+
61
+			msg := &zeroLoggerLogMessage{}
62
+			assert.NoError(t, json.Unmarshal(buf.Bytes(), msg))
63
+
64
+			timestamp := time.Unix(msg.Timestamp/1000, (msg.Timestamp%1000)*1_000_000)
65
+			assert.WithinDuration(t, time.Now(), timestamp, 100*time.Millisecond)
66
+
67
+			assert.Equal(t, level, msg.Level)
68
+			assert.Equal(t, name, msg.StrParam)
69
+			assert.EqualValues(t, 1, msg.IntParam)
70
+			assert.Equal(t, "name", msg.Logger)
71
+			assert.Equal(t, "hello", msg.Message)
72
+
73
+			if level != name {
74
+				assert.Equal(t, io.EOF.Error(), msg.Error)
75
+			} else {
76
+				assert.Empty(t, msg.Error)
77
+			}
78
+		})
79
+	}
80
+}
81
+
82
+func (suite *ZeroLoggerTestSuite) TestIndependence() {
83
+	buf := &bytes.Buffer{}
84
+	log := logger.NewZeroLogger(zerolog.New(buf).With().Timestamp().Logger())
85
+
86
+	log1 := log.Named("1")
87
+	log2 := log.Named("2")
88
+	log12 := log1.Named("2")
89
+
90
+	log1.BindInt("param", 1).Info("hello")
91
+
92
+	log1Output := buf.String()
93
+
94
+	buf.Reset()
95
+
96
+	log2.BindInt("lalala", 2).Info("hello")
97
+
98
+	log2Output := buf.String()
99
+
100
+	buf.Reset()
101
+
102
+	log12.BindStr("tttt", "qqq").Info("hello")
103
+
104
+	log12Output := buf.String()
105
+
106
+	suite.NotContains("lalala", log1Output)
107
+	suite.NotContains("tttt", log1Output)
108
+	suite.NotContains("param", log2Output)
109
+	suite.NotContains("tttt", log1Output)
110
+	suite.NotContains("param", log12Output)
111
+	suite.NotContains("lalala", log12Output)
112
+}
113
+
114
+func TestZeroLogger(t *testing.T) { // nolint: paralleltest
115
+	suite.Run(t, &ZeroLoggerTestSuite{})
116
+}

Chargement…
Annuler
Enregistrer