Skip to content

Instantly share code, notes, and snippets.

@StevenACoffman
Forked from bdimcheff/gokitlogrus.go
Last active March 24, 2023 08:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StevenACoffman/f40729d37200994a929c6ad9d08e68f3 to your computer and use it in GitHub Desktop.
Save StevenACoffman/f40729d37200994a929c6ad9d08e68f3 to your computer and use it in GitHub Desktop.
gokit -> logrus adapter
package log
import (
"fmt"
gokitlog "github.com/go-kit/kit/log"
"github.com/sirupsen/logrus"
stackdriver "github.com/icco/logrus-stackdriver-formatter"
)
var log = logrus.New()
func init() {
log.Formatter = stackdriver.NewFormatter(
stackdriver.WithService("your-service"),
stackdriver.WithVersion("v0.1.0"),
)
log.Level = logrus.DebugLevel
log.Info("ready to log!")
}
type logrusLogger interface {
WithFields(fields logrus.Fields) *logrus.Entry
}
// NewLogrusGoKitLogger wraps a logrus instance and implements the GoKit Logger interface
func NewLogrusGoKitLogger(logger logrusLogger) *LogrusGoKitLogger {
return &LogrusGoKitLogger{logger}
}
// LogrusGoKitLogger is the concrete implementation of the logging wrapper
type LogrusGoKitLogger struct {
logrusLogger
}
const msgKey = "msg"
const errKey = "err"
const levelKey = "level"
// Log implements the fundamental Logger interface
func (l LogrusGoKitLogger) Log(keyvals ...interface{}) error {
fields, level, msg := l.extractLogElements(keyvals...)
entry := l.WithFields(fields)
entry.Log(level, msg)
return nil
}
// extractLogElements iterates through the keyvals to form well
// structuredkey:value pairs that Logrus expects. It also checks for keys with
// special meaning like "msg" and "level" to format the log entry
func (l LogrusGoKitLogger) extractLogElements(keyvals ...interface{}) (fields logrus.Fields, level logrus.Level, msg string) {
msg = ""
fields = logrus.Fields{}
level = logrus.DebugLevel
for i := 0; i < len(keyvals); i += 2 {
if i+1 < len(keyvals) {
if fmt.Sprint(keyvals[i]) == msgKey && msg == "" {
// if this is a "msg" key, store it separately so we can use it as the
// main log message
msg = fmt.Sprint(keyvals[i+1])
} else if fmt.Sprint(keyvals[i]) == errKey {
// if this is a "err" key, we should use the error message as
// the main message and promote the level to Error
err := fmt.Sprint(keyvals[i+1])
if err != "" {
msg = err
level = logrus.ErrorLevel
}
} else if fmt.Sprint(keyvals[i]) == levelKey {
// if this is a "level" key, it means GoKit logger is giving us
// a hint to the logging level
levelStr := fmt.Sprint(keyvals[i+1])
parsedLevel, err := logrus.ParseLevel(levelStr)
if err != nil || level < parsedLevel {
level = logrus.ErrorLevel
fields["level"] = levelStr
} else {
level = parsedLevel
}
} else {
// this is just regular log data, add it as a key:value pair
fields[fmt.Sprint(keyvals[i])] = keyvals[i+1]
}
} else {
// odd pair key, with no matching value
fields[fmt.Sprint(keyvals[i])] = gokitlog.ErrMissingValue
}
}
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment