package web import ( "net/http" "runtime/debug" "time" "github.com/go-chi/chi/v5/middleware" "github.com/rs/zerolog/log" ) func requestLogger(next http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor) t1 := time.Now() defer func() { t2 := time.Now() // Recover and record stack traces in case of a panic if rec := recover(); rec != nil { log.Error(). Str("type", "error"). Timestamp(). Interface("recover_info", rec). Bytes("debug_stack", debug.Stack()). Msg("Handler panicked") http.Error(ww, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } // log end request log.Info(). Timestamp(). Str("remote_ip", r.RemoteAddr). Str("url", r.URL.Path). Str("proto", r.Proto). Str("method", r.Method). Int("status", ww.Status()). Dur("elapsed", t2.Sub(t1)). Int64("bytes_in", r.ContentLength). Int("bytes_out", ww.BytesWritten()). Msg(r.Method + " " + r.URL.Path) }() next.ServeHTTP(ww, r) } return http.HandlerFunc(fn) }