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"
"net/http"
"strings"
"time"
"gitea.dwysokinski.me/Kichiyaki/chizap"
"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
}
```

View File

@ -2,7 +2,6 @@ package chizap
import (
"net/http"
"time"
"go.uber.org/zap"
)
@ -13,16 +12,13 @@ type AdditionalFieldExtractor func(r *http.Request) []zap.Field
type config struct {
filters []Filter
timeFormat string
additionalFieldExtractors []AdditionalFieldExtractor
}
type Option func(*config)
func newConfig(opts ...Option) *config {
cfg := &config{
timeFormat: time.RFC3339,
}
cfg := &config{}
for _, opt := range opts {
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
// request and the returned fields will be added to a log entry.
func WithAdditionalFieldExtractor(extractor AdditionalFieldExtractor) Option {

View File

@ -4,6 +4,7 @@ import (
"net/http"
"time"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"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.Int("contentSize", ww.BytesWritten()),
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 {

View File

@ -24,26 +24,30 @@ func TestLogger(t *testing.T) {
req *http.Request
excluded bool
expectedLevel zapcore.Level
expectedRoutePattern string
expectedTimeFormat string
expectedAdditionalFields []zap.Field
}{
{
name: "/info?test=true",
req: httptest.NewRequest(http.MethodGet, "/info?test=true", nil),
expectedLevel: zap.InfoLevel,
expectedTimeFormat: time.RFC3339,
name: "/info?test=true",
req: httptest.NewRequest(http.MethodGet, "/info?test=true", nil),
expectedLevel: zap.InfoLevel,
expectedTimeFormat: time.RFC3339,
expectedRoutePattern: "/info",
},
{
name: "/warn?test=true",
req: httptest.NewRequest(http.MethodGet, "/warn?test=true", nil),
expectedLevel: zap.WarnLevel,
expectedTimeFormat: time.RFC3339,
name: "/warn?test=true",
req: httptest.NewRequest(http.MethodGet, "/warn?test=true", nil),
expectedLevel: zap.WarnLevel,
expectedTimeFormat: time.RFC3339,
expectedRoutePattern: "/warn",
},
{
name: "/error?test=true",
req: httptest.NewRequest(http.MethodGet, "/error?test=true", nil),
expectedLevel: zap.ErrorLevel,
expectedTimeFormat: time.RFC3339,
name: "/error?test=true",
req: httptest.NewRequest(http.MethodGet, "/error?test=true", nil),
expectedLevel: zap.ErrorLevel,
expectedTimeFormat: time.RFC3339,
expectedRoutePattern: "/error",
},
{
name: "/excluded?test=true",
@ -51,20 +55,15 @@ func TestLogger(t *testing.T) {
excluded: true,
},
{
name: "/delete/123",
req: httptest.NewRequest(http.MethodDelete, "/delete/123", nil),
expectedLevel: zap.InfoLevel,
expectedTimeFormat: time.RFC3339,
name: "/delete/123",
req: httptest.NewRequest(http.MethodDelete, "/delete/123", nil),
expectedLevel: zap.InfoLevel,
expectedTimeFormat: time.RFC3339,
expectedRoutePattern: "/delete/{id}",
expectedAdditionalFields: []zap.Field{
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 {
@ -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("path", tt.req.URL.Path))
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 {
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
}
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)
}