package middleware import ( "net/http" "runtime/debug" "time" "github.com/go-chi/chi/v5/middleware" "github.com/rs/zerolog" ) func Logger(logger *zerolog.Logger) func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { log := logger.With().Logger() ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor) t1 := time.Now() defer func() { t2 := time.Now() if rec := recover(); rec != nil { log.Error(). Str("type", "error"). Timestamp(). Interface("recover_info", rec). Bytes("debug_stack", debug.Stack()). Msg("log system error") http.Error(ww, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } log.Info(). Str("type", "access"). Timestamp(). Fields(map[string]interface{}{ "remote_ip": r.RemoteAddr, "url": r.URL.Path, "proto": r.Proto, "method": r.Method, "user_agent": r.Header.Get("User-Agent"), "status": ww.Status(), "latency_ms": float64(t2.Sub(t1).Nanoseconds()) / 1000000.0, "bytes_in": r.Header.Get("Content-Length"), "bytes_out": ww.BytesWritten(), }). Msg("incoming_request") }() next.ServeHTTP(ww, r) } return http.HandlerFunc(fn) } }