From 509b4d76f9fb6eae09f223b40a5978387419188e Mon Sep 17 00:00:00 2001 From: maru <1249107551@qq.com> Date: Thu, 4 Apr 2019 14:21:47 +0800 Subject: [PATCH] Add a log adapter for zap.Logger --- log/zap/zap_sugar_logger.go | 40 +++++++++++++++ log/zap/zap_sugar_logger_test.go | 86 ++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 log/zap/zap_sugar_logger.go create mode 100644 log/zap/zap_sugar_logger_test.go diff --git a/log/zap/zap_sugar_logger.go b/log/zap/zap_sugar_logger.go new file mode 100644 index 000000000..97fe64587 --- /dev/null +++ b/log/zap/zap_sugar_logger.go @@ -0,0 +1,40 @@ +package zap + +import ( + "github.com/go-kit/kit/log" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +type zapSugarLogger func(msg string, keysAndValues ...interface{}) + +func (l zapSugarLogger) Log(kv ...interface{}) error { + l("", kv...) + return nil +} + +// NewZapSugarLogger returns a Go kit log.Logger that sends +// log events to a zap.Logger. +func NewZapSugarLogger(logger *zap.Logger, level zapcore.Level) log.Logger { + sugarLogger := logger.WithOptions(zap.AddCallerSkip(2)).Sugar() + var sugar zapSugarLogger + switch level { + case zapcore.DebugLevel: + sugar = sugarLogger.Debugw + case zapcore.InfoLevel: + sugar = sugarLogger.Infow + case zapcore.WarnLevel: + sugar = sugarLogger.Warnw + case zapcore.ErrorLevel: + sugar = sugarLogger.Errorw + case zapcore.DPanicLevel: + sugar = sugarLogger.DPanicw + case zapcore.PanicLevel: + sugar = sugarLogger.Panicw + case zapcore.FatalLevel: + sugar = sugarLogger.Fatalw + default: + sugar = sugarLogger.Infow + } + return sugar +} diff --git a/log/zap/zap_sugar_logger_test.go b/log/zap/zap_sugar_logger_test.go new file mode 100644 index 000000000..883ce0aa3 --- /dev/null +++ b/log/zap/zap_sugar_logger_test.go @@ -0,0 +1,86 @@ +package zap_test + +import ( + "encoding/json" + kitzap "github.com/go-kit/kit/log/zap" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "strings" + "testing" +) + +func TestZapSugarLogger(t *testing.T) { + // logger config + encoderConfig := zap.NewDevelopmentEncoderConfig() + encoder := zapcore.NewJSONEncoder(encoderConfig) + levelKey := encoderConfig.LevelKey + // basic test cases + type testCase struct { + level zapcore.Level + kvs []interface{} + want map[string]string + } + testCases := []testCase{ + {level: zapcore.DebugLevel, kvs: []interface{}{"key1", "value1"}, + want: map[string]string{levelKey: "DEBUG", "key1": "value1"}}, + + {level: zapcore.InfoLevel, kvs: []interface{}{"key2", "value2"}, + want: map[string]string{levelKey: "INFO", "key2": "value2"}}, + + {level: zapcore.WarnLevel, kvs: []interface{}{"key3", "value3"}, + want: map[string]string{levelKey: "WARN", "key3": "value3"}}, + + {level: zapcore.ErrorLevel, kvs: []interface{}{"key4", "value4"}, + want: map[string]string{levelKey: "ERROR", "key4": "value4"}}, + + {level: zapcore.DPanicLevel, kvs: []interface{}{"key5", "value5"}, + want: map[string]string{levelKey: "DPANIC", "key5": "value5"}}, + + {level: zapcore.PanicLevel, kvs: []interface{}{"key6", "value6"}, + want: map[string]string{levelKey: "PANIC", "key6": "value6"}}, + } + // test + for _, testCase := range testCases { + t.Run(testCase.level.String(), func(t *testing.T) { + // make logger + writer := &tbWriter{tb: t} + logger := zap.New( + zapcore.NewCore(encoder, zapcore.AddSync(writer), zap.DebugLevel), + zap.Development()) + // check panic + shouldPanic := testCase.level >= zapcore.DPanicLevel + kitLogger := kitzap.NewZapSugarLogger(logger, testCase.level) + defer func() { + isPanic := recover() != nil + if shouldPanic != isPanic { + t.Errorf("test level %v should panic(%v), but %v", testCase.level, shouldPanic, isPanic) + } + // check log kvs + logMap := make(map[string]string) + err := json.Unmarshal([]byte(writer.sb.String()), &logMap) + if err != nil { + t.Errorf("unmarshal error: %v", err) + } else { + for k, v := range testCase.want { + vv, ok := logMap[k] + if !ok || v != vv { + t.Error("error log") + } + } + } + }() + kitLogger.Log(testCase.kvs...) + }) + } +} + +type tbWriter struct { + tb testing.TB + sb strings.Builder +} + +func (w *tbWriter) Write(b []byte) (n int, err error) { + w.tb.Logf(string(b)) + w.sb.Write(b) + return len(b), nil +}