You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

42 lines
959 B

  1. package middleware
  2. import (
  3. "log/slog"
  4. "net/http"
  5. "time"
  6. )
  7. // responseWriter wraps http.ResponseWriter to capture status and bytes written.
  8. type responseWriter struct {
  9. http.ResponseWriter
  10. status int
  11. bytes int
  12. }
  13. func (rw *responseWriter) WriteHeader(code int) {
  14. rw.status = code
  15. rw.ResponseWriter.WriteHeader(code)
  16. }
  17. func (rw *responseWriter) Write(b []byte) (int, error) {
  18. n, err := rw.ResponseWriter.Write(b)
  19. rw.bytes += n
  20. return n, err
  21. }
  22. // Logging logs each request with method, path, status, duration, and bytes written.
  23. func Logging(next http.Handler) http.Handler {
  24. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  25. start := time.Now()
  26. wrap := &responseWriter{ResponseWriter: w, status: http.StatusOK}
  27. next.ServeHTTP(wrap, r)
  28. slog.Info("request",
  29. "method", r.Method,
  30. "path", r.URL.Path,
  31. "status", wrap.status,
  32. "duration_ms", time.Since(start).Milliseconds(),
  33. "bytes", wrap.bytes,
  34. )
  35. })
  36. }