feat: log route pattern
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Dawid Wysokiński 2023-02-02 05:57:50 +01:00
parent 9e49701dd9
commit aed5b142ec
Signed by: Kichiyaki
GPG Key ID: B5445E357FB8B892
4 changed files with 25 additions and 63 deletions

View File

@ -19,7 +19,6 @@ import (
"log" "log"
"net/http" "net/http"
"strings" "strings"
"time"
"gitea.dwysokinski.me/Kichiyaki/chizap" "gitea.dwysokinski.me/Kichiyaki/chizap"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
@ -74,11 +73,6 @@ func newRouter(logger *zap.Logger) *chi.Mux {
}) })
}) })
router.With(chizap.Logger(logger, chizap.WithTimeFormat(time.RFC1123Z))).
Get("/custom-time-format", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
})
return router return router
} }
``` ```

View File

@ -2,7 +2,6 @@ package chizap
import ( import (
"net/http" "net/http"
"time"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -13,16 +12,13 @@ type AdditionalFieldExtractor func(r *http.Request) []zap.Field
type config struct { type config struct {
filters []Filter filters []Filter
timeFormat string
additionalFieldExtractors []AdditionalFieldExtractor additionalFieldExtractors []AdditionalFieldExtractor
} }
type Option func(*config) type Option func(*config)
func newConfig(opts ...Option) *config { func newConfig(opts ...Option) *config {
cfg := &config{ cfg := &config{}
timeFormat: time.RFC3339,
}
for _, opt := range opts { for _, opt := range opts {
opt(cfg) opt(cfg)
@ -41,14 +37,6 @@ func WithFilter(f Filter) Option {
} }
} }
// WithTimeFormat specifies a time format to use for logging a request time.
// time.RFC3339 is used by default.
func WithTimeFormat(f string) Option {
return func(c *config) {
c.timeFormat = f
}
}
// WithAdditionalFieldExtractor takes a function that will be called on every // WithAdditionalFieldExtractor takes a function that will be called on every
// request and the returned fields will be added to a log entry. // request and the returned fields will be added to a log entry.
func WithAdditionalFieldExtractor(extractor AdditionalFieldExtractor) Option { func WithAdditionalFieldExtractor(extractor AdditionalFieldExtractor) Option {

View File

@ -4,6 +4,7 @@ import (
"net/http" "net/http"
"time" "time"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware" "github.com/go-chi/chi/v5/middleware"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -45,7 +46,7 @@ func Logger(logger *zap.Logger, opts ...Option) func(next http.Handler) http.Han
zap.String("referer", r.Referer()), zap.String("referer", r.Referer()),
zap.Int("contentSize", ww.BytesWritten()), zap.Int("contentSize", ww.BytesWritten()),
zap.String("userAgent", r.UserAgent()), zap.String("userAgent", r.UserAgent()),
zap.String("time", end.Format(cfg.timeFormat)), zap.String("routePattern", chi.RouteContext(r.Context()).RoutePattern()),
} }
for _, fn := range cfg.additionalFieldExtractors { for _, fn := range cfg.additionalFieldExtractors {

View File

@ -24,26 +24,30 @@ func TestLogger(t *testing.T) {
req *http.Request req *http.Request
excluded bool excluded bool
expectedLevel zapcore.Level expectedLevel zapcore.Level
expectedRoutePattern string
expectedTimeFormat string expectedTimeFormat string
expectedAdditionalFields []zap.Field expectedAdditionalFields []zap.Field
}{ }{
{ {
name: "/info?test=true", name: "/info?test=true",
req: httptest.NewRequest(http.MethodGet, "/info?test=true", nil), req: httptest.NewRequest(http.MethodGet, "/info?test=true", nil),
expectedLevel: zap.InfoLevel, expectedLevel: zap.InfoLevel,
expectedTimeFormat: time.RFC3339, expectedTimeFormat: time.RFC3339,
expectedRoutePattern: "/info",
}, },
{ {
name: "/warn?test=true", name: "/warn?test=true",
req: httptest.NewRequest(http.MethodGet, "/warn?test=true", nil), req: httptest.NewRequest(http.MethodGet, "/warn?test=true", nil),
expectedLevel: zap.WarnLevel, expectedLevel: zap.WarnLevel,
expectedTimeFormat: time.RFC3339, expectedTimeFormat: time.RFC3339,
expectedRoutePattern: "/warn",
}, },
{ {
name: "/error?test=true", name: "/error?test=true",
req: httptest.NewRequest(http.MethodGet, "/error?test=true", nil), req: httptest.NewRequest(http.MethodGet, "/error?test=true", nil),
expectedLevel: zap.ErrorLevel, expectedLevel: zap.ErrorLevel,
expectedTimeFormat: time.RFC3339, expectedTimeFormat: time.RFC3339,
expectedRoutePattern: "/error",
}, },
{ {
name: "/excluded?test=true", name: "/excluded?test=true",
@ -51,20 +55,15 @@ func TestLogger(t *testing.T) {
excluded: true, excluded: true,
}, },
{ {
name: "/delete/123", name: "/delete/123",
req: httptest.NewRequest(http.MethodDelete, "/delete/123", nil), req: httptest.NewRequest(http.MethodDelete, "/delete/123", nil),
expectedLevel: zap.InfoLevel, expectedLevel: zap.InfoLevel,
expectedTimeFormat: time.RFC3339, expectedTimeFormat: time.RFC3339,
expectedRoutePattern: "/delete/{id}",
expectedAdditionalFields: []zap.Field{ expectedAdditionalFields: []zap.Field{
zap.String("id", "123"), zap.String("id", "123"),
}, },
}, },
{
name: "/custom-time-format",
req: httptest.NewRequest(http.MethodGet, "/custom-time-format", nil),
expectedLevel: zap.InfoLevel,
expectedTimeFormat: time.RFC1123Z,
},
} }
for _, tt := range tests { for _, tt := range tests {
@ -94,17 +93,10 @@ func TestLogger(t *testing.T) {
assert.Contains(t, entry.Context, zap.String("method", tt.req.Method)) assert.Contains(t, entry.Context, zap.String("method", tt.req.Method))
assert.Contains(t, entry.Context, zap.String("path", tt.req.URL.Path)) assert.Contains(t, entry.Context, zap.String("path", tt.req.URL.Path))
assert.Contains(t, entry.Context, zap.String("query", tt.req.URL.RawQuery)) assert.Contains(t, entry.Context, zap.String("query", tt.req.URL.RawQuery))
assert.Contains(t, entry.Context, zap.String("routePattern", tt.expectedRoutePattern))
for _, f := range tt.expectedAdditionalFields { for _, f := range tt.expectedAdditionalFields {
assert.Contains(t, entry.Context, f) assert.Contains(t, entry.Context, f)
} }
for _, f := range entry.Context {
if f.Key != "time" {
continue
}
assertTime(t, tt.expectedTimeFormat, f.String)
break
}
}) })
} }
} }
@ -154,18 +146,5 @@ func newRouter(logger *zap.Logger) *chi.Mux {
}) })
}) })
router.With(chizap.Logger(logger, chizap.WithTimeFormat(time.RFC1123Z))).
Get("/custom-time-format", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
})
return router return router
} }
func assertTime(tb testing.TB, format, timeStr string) {
tb.Helper()
end, err := time.Parse(format, timeStr)
assert.NoError(tb, err)
assert.WithinDuration(tb, end, time.Now(), 1*time.Second)
}