package logger import ( "net/http" "time" "github.com/lukaszraczylo/gohoarder/pkg/uuid" "github.com/rs/zerolog/log" ) // responseWriter wraps http.ResponseWriter to capture status code type responseWriter struct { http.ResponseWriter statusCode int written int64 } func (rw *responseWriter) WriteHeader(code int) { rw.statusCode = code rw.ResponseWriter.WriteHeader(code) } func (rw *responseWriter) Write(b []byte) (int, error) { n, err := rw.ResponseWriter.Write(b) rw.written += int64(n) return n, err } // Middleware is HTTP middleware for request logging func Middleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() // Generate request ID requestID := r.Header.Get("X-Request-ID") if requestID == "" { requestID = "req_" + uuid.New().String()[:8] } // Wrap response writer rw := &responseWriter{ ResponseWriter: w, statusCode: http.StatusOK, } // Set request ID in response header rw.Header().Set("X-Request-ID", requestID) // Call next handler next.ServeHTTP(rw, r) // Log request duration := time.Since(start) log.Info(). Str("request_id", requestID). Str("method", r.Method). Str("path", r.URL.Path). Str("remote_addr", r.RemoteAddr). Str("user_agent", r.UserAgent()). Int("status", rw.statusCode). Int64("bytes", rw.written). Dur("duration_ms", duration). Msg("HTTP request") }) }