blob: 0dcfa26ac19bf11452bd8fceb552ff04606af768 [file] [log] [blame]
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package logr is a logr implementation that uses events.
package logr
import (
"context"
"github.com/go-logr/logr"
"golang.org/x/exp/event"
"golang.org/x/exp/event/severity"
)
type logSink struct {
ev *event.Event // cloned, never delivered
labels []event.Label
nameSep string
name string
verbosity int
}
func NewLogger(ctx context.Context, nameSep string) logr.Logger {
return logr.New(&logSink{
ev: event.New(ctx, event.LogKind),
nameSep: nameSep,
})
}
func (*logSink) Init(logr.RuntimeInfo) {}
// WithName implements logr.LogSink.WithName.
func (l *logSink) WithName(name string) logr.LogSink {
l2 := *l
if l.name == "" {
l2.name = name
} else {
l2.name = l.name + l.nameSep + name
}
return &l2
}
// Enabled tests whether this LogSink is enabled at the specified V-level.
// For example, commandline flags might be used to set the logging
// verbosity and disable some info logs.
func (l *logSink) Enabled(level int) bool {
return true
}
// Info implements logr.LogSink.Info.
func (l *logSink) Info(level int, msg string, keysAndValues ...interface{}) {
if l.ev == nil {
return
}
ev := l.ev.Clone()
ev.Labels = append(ev.Labels, convertVerbosity(level).Label())
l.log(ev, msg, keysAndValues)
}
// Error implements logr.LogSink.Error.
func (l *logSink) Error(err error, msg string, keysAndValues ...interface{}) {
if l.ev == nil {
return
}
ev := l.ev.Clone()
ev.Labels = append(ev.Labels, event.Value("error", err))
l.log(ev, msg, keysAndValues)
}
func (l *logSink) log(ev *event.Event, msg string, keysAndValues []interface{}) {
ev.Labels = append(ev.Labels)
ev.Labels = append(ev.Labels, l.labels...)
for i := 0; i < len(keysAndValues); i += 2 {
ev.Labels = append(ev.Labels, newLabel(keysAndValues[i], keysAndValues[i+1]))
}
ev.Labels = append(ev.Labels,
event.String("name", l.name),
event.String("msg", msg),
)
ev.Deliver()
}
// WithValues implements logr.LogSink.WithValues.
func (l *logSink) WithValues(keysAndValues ...interface{}) logr.LogSink {
l2 := *l
if len(keysAndValues) > 0 {
l2.labels = make([]event.Label, len(l.labels), len(l.labels)+(len(keysAndValues)/2))
copy(l2.labels, l.labels)
for i := 0; i < len(keysAndValues); i += 2 {
l2.labels = append(l2.labels, newLabel(keysAndValues[i], keysAndValues[i+1]))
}
}
return &l2
}
func newLabel(key, value interface{}) event.Label {
return event.Value(key.(string), value)
}
func convertVerbosity(v int) severity.Level {
//TODO: this needs to be more complicated, v decreases with increasing severity
return severity.Level(v)
}