Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/util/zapadapter/zapadapter.go
4094 views
1
// Package zapadapter allows github.com/go-kit/log to be used as a Zap core.
2
package zapadapter
3
4
import (
5
"fmt"
6
"strings"
7
"sync"
8
"time"
9
10
"github.com/go-kit/log"
11
"github.com/go-kit/log/level"
12
"go.uber.org/zap"
13
"go.uber.org/zap/zapcore"
14
)
15
16
// New returns a new zap.Logger instance which will forward logs to the
17
// provided log.Logger. The github.com/go-kit/log/level package will be used
18
// for specifying log levels.
19
func New(l log.Logger) *zap.Logger {
20
return zap.New(&loggerCore{inner: l})
21
}
22
23
// loggerCore is a zap.Core implementation which forwards logs to a log.Logger
24
// instance.
25
type loggerCore struct {
26
inner log.Logger
27
}
28
29
var _ zapcore.Core = (*loggerCore)(nil)
30
31
// Enabled implements zapcore.Core and returns whether logs at a specific level
32
// should be reported.
33
func (lc *loggerCore) Enabled(zapcore.Level) bool {
34
// An instance of log.Logger has no way of knowing if logs will be filtered
35
// out, so we always have to return true here.
36
return true
37
}
38
39
// With implements zapcore.Core, returning a new logger core with ff appended
40
// to the list of fields.
41
func (lc *loggerCore) With(ff []zapcore.Field) zapcore.Core {
42
// Encode all of the fields so that they're go-kit compatible and create a
43
// new logger from it.
44
enc := newFieldEncoder()
45
defer func() { _ = enc.Close() }()
46
47
for _, f := range ff {
48
f.AddTo(enc)
49
}
50
51
return &loggerCore{
52
inner: log.With(lc.inner, enc.fields...),
53
}
54
}
55
56
// Check implements zapcore.Core. lc will always add itself along with the
57
// provided entry to the CheckedEntry.
58
func (lc *loggerCore) Check(e zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
59
return ce.AddCore(e, lc)
60
}
61
62
// Write serializes e with the provided list of fields, writing them to the
63
// underlying github.com/go-kit/log.Logger instance.
64
func (lc *loggerCore) Write(e zapcore.Entry, ff []zapcore.Field) error {
65
enc := newFieldEncoder()
66
defer func() { _ = enc.Close() }()
67
68
enc.fields = append(enc.fields, "msg", e.Message)
69
70
for _, f := range ff {
71
f.AddTo(enc)
72
}
73
74
switch e.Level {
75
case zapcore.DebugLevel:
76
return level.Debug(lc.inner).Log(enc.fields...)
77
case zapcore.InfoLevel:
78
return level.Info(lc.inner).Log(enc.fields...)
79
case zapcore.WarnLevel:
80
return level.Warn(lc.inner).Log(enc.fields...)
81
case zapcore.ErrorLevel, zapcore.DPanicLevel, zapcore.PanicLevel, zapcore.FatalLevel:
82
// We ignore panics/fatals here because we really don't want components to
83
// be able to do that.
84
return level.Error(lc.inner).Log(enc.fields...)
85
default:
86
return lc.inner.Log(enc.fields...)
87
}
88
}
89
90
func (lc *loggerCore) Sync() error {
91
return nil
92
}
93
94
// fieldEncoder implements zapcore.ObjectEncoder. It enables converting a
95
// zapcore.Field into a value which will be written as a github.com/go-kit/log
96
// keypair.
97
type fieldEncoder struct {
98
// fields are the list of fields that will be passed to log.Logger.Log.
99
fields []interface{}
100
101
// namespace is used to prefix keys before appending to fields. When a
102
// zap.Namespace field is logged, the OpenNamespace method of the
103
// fieldEncoder will be invoked, appending to the namespace slice.
104
//
105
// It is not possible to pop a namespace from the list; once a zap.Namespace
106
// field is logged, all further fields in that entry are scoped within that
107
// namespace.
108
namespace []string
109
}
110
111
var _ zapcore.ObjectEncoder = (*fieldEncoder)(nil)
112
113
var encPool = sync.Pool{
114
New: func() any {
115
return &fieldEncoder{}
116
},
117
}
118
119
// newFieldEncoder creates a ready-to-use fieldEncoder. Call Close once the
120
// fieldEncoder is no longer needed.
121
func newFieldEncoder() *fieldEncoder {
122
fe := encPool.Get().(*fieldEncoder)
123
fe.fields = fe.fields[:0]
124
fe.namespace = fe.namespace[:0]
125
return fe
126
}
127
128
func (fe *fieldEncoder) Close() error {
129
encPool.Put(fe)
130
return nil
131
}
132
133
func (fe *fieldEncoder) AddArray(key string, marshaler zapcore.ArrayMarshaler) error {
134
// TODO(rfratto): allow this to write the value of the array instead of
135
// placeholder text.
136
fe.fields = append(fe.fields, fe.keyName(key), "<array>")
137
return nil
138
}
139
140
func (fe *fieldEncoder) AddObject(key string, marshaler zapcore.ObjectMarshaler) error {
141
// TODO(rfratto): allow this to write the value of the object instead of
142
// placeholder text.
143
fe.fields = append(fe.fields, fe.keyName(key), "<object>")
144
return nil
145
}
146
147
func (fe *fieldEncoder) AddBinary(key string, value []byte) {
148
fe.fields = append(fe.fields, fe.keyName(key), value)
149
}
150
151
func (fe *fieldEncoder) AddByteString(key string, value []byte) {
152
fe.fields = append(fe.fields, fe.keyName(key), string(value))
153
}
154
155
func (fe *fieldEncoder) AddBool(key string, value bool) {
156
fe.fields = append(fe.fields, fe.keyName(key), value)
157
}
158
159
func (fe *fieldEncoder) AddComplex128(key string, value complex128) {
160
fe.fields = append(fe.fields, fe.keyName(key), value)
161
}
162
163
func (fe *fieldEncoder) AddComplex64(key string, value complex64) {
164
fe.fields = append(fe.fields, fe.keyName(key), value)
165
}
166
167
func (fe *fieldEncoder) AddDuration(key string, value time.Duration) {
168
fe.fields = append(fe.fields, fe.keyName(key), value)
169
}
170
171
func (fe *fieldEncoder) AddFloat64(key string, value float64) {
172
fe.fields = append(fe.fields, fe.keyName(key), value)
173
}
174
175
func (fe *fieldEncoder) AddFloat32(key string, value float32) {
176
fe.fields = append(fe.fields, fe.keyName(key), value)
177
}
178
179
func (fe *fieldEncoder) AddInt(key string, value int) {
180
fe.fields = append(fe.fields, fe.keyName(key), value)
181
}
182
183
func (fe *fieldEncoder) AddInt64(key string, value int64) {
184
fe.fields = append(fe.fields, fe.keyName(key), value)
185
}
186
187
func (fe *fieldEncoder) AddInt32(key string, value int32) {
188
fe.fields = append(fe.fields, fe.keyName(key), value)
189
}
190
191
func (fe *fieldEncoder) AddInt16(key string, value int16) {
192
fe.fields = append(fe.fields, fe.keyName(key), value)
193
}
194
195
func (fe *fieldEncoder) AddInt8(key string, value int8) {
196
fe.fields = append(fe.fields, fe.keyName(key), value)
197
}
198
199
func (fe *fieldEncoder) AddString(key, value string) {
200
fe.fields = append(fe.fields, fe.keyName(key), value)
201
}
202
203
func (fe *fieldEncoder) AddTime(key string, value time.Time) {
204
fe.fields = append(fe.fields, fe.keyName(key), value)
205
}
206
207
func (fe *fieldEncoder) AddUint(key string, value uint) {
208
fe.fields = append(fe.fields, fe.keyName(key), value)
209
}
210
211
func (fe *fieldEncoder) AddUint64(key string, value uint64) {
212
fe.fields = append(fe.fields, fe.keyName(key), value)
213
}
214
215
func (fe *fieldEncoder) AddUint32(key string, value uint32) {
216
fe.fields = append(fe.fields, fe.keyName(key), value)
217
}
218
219
func (fe *fieldEncoder) AddUint16(key string, value uint16) {
220
fe.fields = append(fe.fields, fe.keyName(key), value)
221
}
222
223
func (fe *fieldEncoder) AddUint8(key string, value uint8) {
224
fe.fields = append(fe.fields, fe.keyName(key), value)
225
}
226
227
func (fe *fieldEncoder) AddUintptr(key string, value uintptr) {
228
fe.fields = append(fe.fields, fe.keyName(key), value)
229
}
230
231
func (fe *fieldEncoder) AddReflected(key string, value interface{}) error {
232
fe.fields = append(fe.fields, fe.keyName(key), value)
233
return nil
234
}
235
236
func (fe *fieldEncoder) OpenNamespace(key string) {
237
fe.namespace = append(fe.namespace, key)
238
}
239
240
// keyName returns the key to used for a named field. If the fieldEncoder isn't
241
// namespaced, then the key name is k. Otherwise, the key name the combined
242
// string of the namespace and key, delimiting each fragment by a period `.`.
243
func (fe *fieldEncoder) keyName(k string) interface{} {
244
if len(fe.namespace) == 0 {
245
return k
246
}
247
return key(append(fe.namespace, k))
248
}
249
250
type key []string
251
252
var _ fmt.Stringer = (key)(nil)
253
254
func (k key) String() string {
255
if len(k) == 1 {
256
return k[0]
257
}
258
return strings.Join(k, ".")
259
}
260
261