package middleware import ( "log/slog" "net/http" "time" ) type responseWriter struct { http.ResponseWriter status int size int } func (rw *responseWriter) WriteHeader(status int) { rw.status = status rw.ResponseWriter.WriteHeader(status) } func (rw *responseWriter) Write(b []byte) (int, error) { n, err := rw.ResponseWriter.Write(b) rw.size += n return n, err } // Logging emits a single structured log line per request once the handler // returns. The status code defaults to 200 if the handler never explicitly // calls WriteHeader. func Logging(logger *slog.Logger) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() rw := &responseWriter{ResponseWriter: w, status: http.StatusOK} next.ServeHTTP(rw, r) logger.Info("http request", "method", r.Method, "path", r.URL.Path, "status", rw.status, "size", rw.size, "duration", time.Since(start), "request_id", GetRequestID(r.Context()), ) }) } }