diff --git a/README.md b/README.md index a8e5cd2..b621336 100644 --- a/README.md +++ b/README.md @@ -189,6 +189,15 @@ c = c.Append(hlog.NewHandler(log)) // Install some provided extra handler to set some request's context fields. // Thanks to those handler, all our logs will come with some pre-populated fields. +c = c.Append(hlog.AccessHandler(func(r *http.Request, status, size int, duration time.Duration) { + hlog.FromRequest(r).Info(). + Str("method", r.Method). + Str("url", r.URL.String()). + Int("status", status). + Int("size", size). + Dur("duration", duration). + Msg("") +})) c = c.Append(hlog.RemoteAddrHandler("ip")) c = c.Append(hlog.UserAgentHandler("user_agent")) c = c.Append(hlog.RefererHandler("referer")) diff --git a/hlog/hlog.go b/hlog/hlog.go index 40bb669..084ae45 100644 --- a/hlog/hlog.go +++ b/hlog/hlog.go @@ -5,10 +5,12 @@ import ( "context" "net" "net/http" + "time" "github.com/rs/xid" "github.com/rs/zerolog" "github.com/rs/zerolog/log" + "github.com/zenazn/goji/web/mutil" ) // FromRequest gets the logger in the request's context. @@ -152,3 +154,15 @@ func RequestIDHandler(fieldKey, headerName string) func(next http.Handler) http. }) } } + +// AccessHandler returns a handler that call f after each request. +func AccessHandler(f func(r *http.Request, status, size int, duration time.Duration)) func(next http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + start := time.Now() + lw := mutil.WrapWriter(w) + next.ServeHTTP(lw, r) + f(r, lw.Status(), lw.BytesWritten(), time.Since(start)) + }) + } +}