Repository: go-kratos/kratos
Pull request #2942 (2023-08-03 09:30:51)

feat(contrib): add zerolog


Patch:
diff --git a/contrib/config/nacos/go.sum b/contrib/config/nacos/go.sum
index c036030d..3830a339 100644
--- a/contrib/config/nacos/go.sum
+++ b/contrib/config/nacos/go.sum
@@ -2,6 +2,7 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/aliyun/alibaba-cloud-sdk-go v1.61.18 h1:zOVTBdCKFd9JbCKz9/nt+FovbjPFmb7mUnp8nH9fQBA=
 github.com/aliyun/alibaba-cloud-sdk-go v1.61.18/go.mod h1:v8ESoHo4SyHmuB4b1tJqDHxfTGEciD+yhvOU/5s1Rfk=
+github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
 github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
 github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
diff --git a/contrib/log/zerolog/go.mod b/contrib/log/zerolog/go.mod
new file mode 100644
index 00000000..048ec449
--- /dev/null
+++ b/contrib/log/zerolog/go.mod
@@ -0,0 +1,14 @@
+module github.com/go-kratos/kratos/contrib/log/zerolog/v2
+
+go 1.19
+
+require (
+	github.com/go-kratos/kratos/v2 v2.6.3
+	github.com/rs/zerolog v1.30.0
+)
+
+require (
+	github.com/mattn/go-colorable v0.1.12 // indirect
+	github.com/mattn/go-isatty v0.0.14 // indirect
+	golang.org/x/sys v0.8.0 // indirect
+)
diff --git a/contrib/log/zerolog/go.sum b/contrib/log/zerolog/go.sum
new file mode 100644
index 00000000..219247d0
--- /dev/null
+++ b/contrib/log/zerolog/go.sum
@@ -0,0 +1,16 @@
+github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
+github.com/go-kratos/kratos/v2 v2.6.3 h1:zuejN8CnszyMnbLWd7ObCN9rLuKucJe2/2P6hHpePDc=
+github.com/go-kratos/kratos/v2 v2.6.3/go.mod h1:nlBMkZueZps7UaP3GdbqG8V8N/eAX0jh019OKSm4xew=
+github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
+github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
+github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
+github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c=
+github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/contrib/log/zerolog/zerolog.go b/contrib/log/zerolog/zerolog.go
new file mode 100644
index 00000000..bca49ba0
--- /dev/null
+++ b/contrib/log/zerolog/zerolog.go
@@ -0,0 +1,54 @@
+package zerolog
+
+import (
+	"github.com/rs/zerolog"
+
+	"github.com/go-kratos/kratos/v2/log"
+)
+
+var _ log.Logger = (*Logger)(nil)
+
+type Logger struct {
+	log *zerolog.Logger
+}
+
+func NewLogger(logger *zerolog.Logger) log.Logger {
+	return &Logger{
+		log: logger,
+	}
+}
+
+func (l *Logger) Log(level log.Level, keyvals ...interface{}) (err error) {
+	var event *zerolog.Event
+	if len(keyvals) == 0 {
+		return nil
+	}
+	if len(keyvals)%2 != 0 {
+		keyvals = append(keyvals, "")
+	}
+
+	switch level {
+	case log.LevelDebug:
+		event = l.log.Debug()
+	case log.LevelInfo:
+		event = l.log.Info()
+	case log.LevelWarn:
+		event = l.log.Warn()
+	case log.LevelError:
+		event = l.log.Error()
+	case log.LevelFatal:
+		event = l.log.Fatal()
+	default:
+		event = l.log.Debug()
+	}
+
+	for i := 0; i < len(keyvals); i += 2 {
+		key, ok := keyvals[i].(string)
+		if !ok {
+			continue
+		}
+		event = event.Any(key, keyvals[i+1])
+	}
+	event.Send()
+	return
+}
diff --git a/transport/http/server.go b/transport/http/server.go
index 31a3c95e..9958a08a 100644
--- a/transport/http/server.go
+++ b/transport/http/server.go
@@ -220,6 +220,14 @@ func (s *Server) WalkRoute(fn WalkRouteFunc) error {
 	})
 }
 
+// WalkHandle walks the router and all its sub-routers, calling walkFn for each route in the tree.
+func (s *Server) WalkHandle(handle func(method, path string, handler http.HandlerFunc)) error {
+	return s.WalkRoute(func(r RouteInfo) error {
+		handle(r.Method, r.Path, s.ServeHTTP)
+		return nil
+	})
+}
+
 // Route registers an HTTP router.
 func (s *Server) Route(prefix string, filters ...FilterFunc) *Router {
 	return newRouter(prefix, s, filters...)


Test patch:
diff --git a/contrib/log/zerolog/zerolog_test.go b/contrib/log/zerolog/zerolog_test.go
new file mode 100644
index 00000000..4f3714b5
--- /dev/null
+++ b/contrib/log/zerolog/zerolog_test.go
@@ -0,0 +1,45 @@
+package zerolog
+
+import (
+	"testing"
+
+	"github.com/rs/zerolog"
+
+	"github.com/go-kratos/kratos/v2/log"
+)
+
+type testWriteSyncer struct {
+	output []string
+}
+
+func (x *testWriteSyncer) Write(p []byte) (n int, err error) {
+	x.output = append(x.output, string(p))
+	return len(p), nil
+}
+
+func TestLogger(t *testing.T) {
+	syncer := &testWriteSyncer{}
+	zerolog.TimeFieldFormat = "2006-01-02 15:04:05.000"
+	zlogger := zerolog.New(syncer)
+	logger := NewLogger(&zlogger)
+
+	klog := log.NewHelper(logger)
+
+	klog.Debugw("log", "debug")
+	klog.Infow("log", "info")
+	klog.Warnw("log", "warn")
+	klog.Errorw("log", "error")
+
+	except := []string{
+		"{\"level\":\"debug\",\"log\":\"debug\"}\n",
+		"{\"level\":\"info\",\"log\":\"info\"}\n",
+		"{\"level\":\"warn\",\"log\":\"warn\"}\n",
+		"{\"level\":\"error\",\"log\":\"error\"}\n",
+	}
+	for i, s := range except {
+		if s != syncer.output[i] {
+			t.Logf("except=%s, got=%s", s, syncer.output[i])
+			t.Fail()
+		}
+	}
+}