From 5b6230967737d8adf49f36693f61f5d43466b7ba Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Sat, 2 Mar 2024 12:36:50 +0800 Subject: [PATCH] feat: implement skip path regexps feature in zap package (#72) - Add a new import statement for `regexp` in `zap.go` - Add a new field `SkipPathRegexps` to the `Config` struct in `zap.go` - Add a new function `GinzapWithConfig` in `zap.go` - Add a new test function `TestSkipPathRegexps` in `zap_test.go` Signed-off-by: appleboy --- zap.go | 23 ++++++++++++++++++----- zap_test.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/zap.go b/zap.go index d9af527..52738cd 100644 --- a/zap.go +++ b/zap.go @@ -7,6 +7,7 @@ import ( "net/http" "net/http/httputil" "os" + "regexp" "runtime/debug" "strings" "time" @@ -29,11 +30,12 @@ type ZapLogger interface { // Config is config setting for Ginzap type Config struct { - TimeFormat string - UTC bool - SkipPaths []string - Context Fn - DefaultLevel zapcore.Level + TimeFormat string + UTC bool + SkipPaths []string + SkipPathRegexps []*regexp.Regexp + Context Fn + DefaultLevel zapcore.Level // skip is a Skipper that indicates which logs should not be written. // Optional. Skipper Skipper @@ -70,6 +72,17 @@ func GinzapWithConfig(logger ZapLogger, conf *Config) gin.HandlerFunc { track = false } + if track && len(conf.SkipPathRegexps) > 0 { + for _, reg := range conf.SkipPathRegexps { + if !reg.MatchString(path) { + continue + } + + track = false + break + } + } + if track { end := time.Now() latency := end.Sub(start) diff --git a/zap_test.go b/zap_test.go index 0e81ca3..4d9d341 100644 --- a/zap_test.go +++ b/zap_test.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" "net/http/httptest" + "regexp" "testing" "time" @@ -178,3 +179,48 @@ func TestLoggerSkipper(t *testing.T) { t.Fatalf("logged path should be /test but %s", pathStr) } } + +func TestSkipPathRegexps(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + r := gin.New() + + rxURL := regexp.MustCompile(`^/no_\s*`) + + utcLogger, utcLoggerObserved := buildDummyLogger() + r.Use(GinzapWithConfig(utcLogger, &Config{ + TimeFormat: time.RFC3339, + UTC: true, + SkipPathRegexps: []*regexp.Regexp{rxURL}, + })) + + r.GET(testPath, func(c *gin.Context) { + c.JSON(204, nil) + }) + + r.GET("/no_log", func(c *gin.Context) { + c.JSON(204, nil) + }) + + res1 := httptest.NewRecorder() + req1, _ := http.NewRequestWithContext(ctx, "GET", testPath, nil) + r.ServeHTTP(res1, req1) + + res2 := httptest.NewRecorder() + req2, _ := http.NewRequestWithContext(ctx, "GET", "/no_log", nil) + r.ServeHTTP(res2, req2) + + if res2.Code != 204 { + t.Fatalf("request /no_log is failed (%d)", res2.Code) + } + + if len(utcLoggerObserved.All()) != 1 { + t.Fatalf("Log should be 1 line but there're %d", len(utcLoggerObserved.All())) + } + + logLine := utcLoggerObserved.All()[0] + pathStr := logLine.Context[2].String + if pathStr != testPath { + t.Fatalf("logged path should be /test but %s", pathStr) + } +}