diff --git a/log/logrus/logrus_logger.go b/log/logrus/logrus_logger.go new file mode 100644 index 000000000..e7e370c94 --- /dev/null +++ b/log/logrus/logrus_logger.go @@ -0,0 +1,35 @@ +// Package logrus provides an adapter to the +// go-kit log.Logger interface. +package logrus + +import ( + "errors" + "fmt" + + "github.com/go-kit/kit/log" + "github.com/sirupsen/logrus" +) + +type logrusLogger struct { + *logrus.Logger +} + +var errMissingValue = errors.New("(MISSING)") + +// NewLogrusLogger returns a go-kit log.Logger that sends log events to a Logrus logger. +func NewLogrusLogger(logger *logrus.Logger) log.Logger { + return &logrusLogger{logger} +} + +func (l logrusLogger) Log(keyvals ...interface{}) error { + fields := logrus.Fields{} + for i := 0; i < len(keyvals); i += 2 { + if i+1 < len(keyvals) { + fields[fmt.Sprint(keyvals[i])] = keyvals[i+1] + } else { + fields[fmt.Sprint(keyvals[i])] = errMissingValue + } + } + l.WithFields(fields).Info() + return nil +} diff --git a/log/logrus/logrus_logger_test.go b/log/logrus/logrus_logger_test.go new file mode 100644 index 000000000..cc656ce0f --- /dev/null +++ b/log/logrus/logrus_logger_test.go @@ -0,0 +1,55 @@ +package logrus_test + +import ( + "bytes" + "errors" + "strings" + "testing" + + log "github.com/go-kit/kit/log/logrus" + "github.com/sirupsen/logrus" +) + +func TestLogrusLogger(t *testing.T) { + t.Parallel() + buf := &bytes.Buffer{} + logrusLogger := logrus.New() + logrusLogger.Out = buf + logrusLogger.Formatter = &logrus.TextFormatter{TimestampFormat: "02-01-2006 15:04:05", FullTimestamp: true} + logger := log.NewLogrusLogger(logrusLogger) + + if err := logger.Log("hello", "world"); err != nil { + t.Fatal(err) + } + if want, have := "hello=world\n", strings.Split(buf.String(), " ")[3]; want != have { + t.Errorf("want %#v, have %#v", want, have) + } + + buf.Reset() + if err := logger.Log("a", 1, "err", errors.New("error")); err != nil { + t.Fatal(err) + } + if want, have := "a=1 err=error", strings.TrimSpace(strings.SplitAfterN(buf.String(), " ", 4)[3]); want != have { + t.Errorf("want %#v, have %#v", want, have) + } + + buf.Reset() + if err := logger.Log("a", 1, "b"); err != nil { + t.Fatal(err) + } + if want, have := "a=1 b=\"(MISSING)\"", strings.TrimSpace(strings.SplitAfterN(buf.String(), " ", 4)[3]); want != have { + t.Errorf("want %#v, have %#v", want, have) + } + + buf.Reset() + if err := logger.Log("my_map", mymap{0: 0}); err != nil { + t.Fatal(err) + } + if want, have := "my_map=special_behavior", strings.TrimSpace(strings.Split(buf.String(), " ")[3]); want != have { + t.Errorf("want %#v, have %#v", want, have) + } +} + +type mymap map[int]int + +func (m mymap) String() string { return "special_behavior" }