-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
logger.go
136 lines (114 loc) · 3.25 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
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package internal
import (
gokitLog "github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
"go.uber.org/zap"
)
const (
levelKey = "level"
msgKey = "msg"
)
// NewZapToGokitLogAdapter create an adapter for zap.Logger to gokitLog.Logger
func NewZapToGokitLogAdapter(logger *zap.Logger) gokitLog.Logger {
// need to skip two levels in order to get the correct caller
// one for this method, the other for gokitLog
logger = logger.WithOptions(zap.AddCallerSkip(2))
return &zapToGokitLogAdapter{l: logger.Sugar()}
}
type zapToGokitLogAdapter struct {
l *zap.SugaredLogger
}
type logData struct {
level level.Value
msg string
otherFields []interface{}
}
func (w *zapToGokitLogAdapter) Log(keyvals ...interface{}) error {
// expecting key value pairs, the number of items need to be even
if len(keyvals)%2 == 0 {
// Extract log level and message and log them using corresponding zap function
ld := extractLogData(keyvals)
logFunc := levelToFunc(w.l, ld.level)
logFunc(ld.msg, ld.otherFields...)
} else {
// in case something goes wrong
w.l.Info(keyvals...)
}
return nil
}
func extractLogData(keyvals []interface{}) *logData {
lvl := level.InfoValue() // default
msg := ""
other := make([]interface{}, 0, len(keyvals))
for i := 0; i < len(keyvals); i += 2 {
key := keyvals[i]
val := keyvals[i+1]
if l, ok := matchLogLevel(key, val); ok {
lvl = l
continue
}
if m, ok := matchLogMessage(key, val); ok {
msg = m
continue
}
other = append(other, key, val)
}
return &logData{
level: lvl,
msg: msg,
otherFields: other,
}
}
// check if a given key-value pair represents go-kit log message and return it
func matchLogMessage(key interface{}, val interface{}) (string, bool) {
strKey, ok := key.(string)
if !ok || strKey != msgKey {
return "", false
}
msg, ok := val.(string)
if !ok {
return "", false
}
return msg, true
}
// check if a given key-value pair represents go-kit log level and return it
func matchLogLevel(key interface{}, val interface{}) (level.Value, bool) {
strKey, ok := key.(string)
if !ok || strKey != levelKey {
return nil, false
}
levelVal, ok := val.(level.Value)
if !ok {
return nil, false
}
return levelVal, true
}
// find a matching zap logging function to be used for a given level
func levelToFunc(logger *zap.SugaredLogger, lvl level.Value) func(string, ...interface{}) {
switch lvl {
case level.DebugValue():
return logger.Debugw
case level.InfoValue():
return logger.Infow
case level.WarnValue():
return logger.Warnw
case level.ErrorValue():
return logger.Errorw
}
// default
return logger.Infof
}
var _ gokitLog.Logger = (*zapToGokitLogAdapter)(nil)