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()),
)
})
}
}