logging.go

 1package server
 2
 3import (
 4	"log/slog"
 5	"net/http"
 6	"time"
 7)
 8
 9func (s *Server) loggingHandler(next http.Handler) http.Handler {
10	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
11		if s.logger == nil {
12			next.ServeHTTP(w, r)
13			return
14		}
15
16		start := time.Now()
17		lrw := &loggingResponseWriter{ResponseWriter: w, statusCode: http.StatusOK}
18		s.logger.Debug(
19			"HTTP request",
20			slog.String("method", r.Method),
21			slog.String("path", r.URL.Path),
22			slog.String("remote_addr", r.RemoteAddr),
23			slog.String("user_agent", r.UserAgent()),
24		)
25
26		next.ServeHTTP(lrw, r)
27		duration := time.Since(start)
28
29		s.logger.Debug(
30			"HTTP response",
31			slog.String("method", r.Method),
32			slog.String("path", r.URL.Path),
33			slog.Int("status", lrw.statusCode),
34			slog.Duration("duration", duration),
35			slog.String("remote_addr", r.RemoteAddr),
36			slog.String("user_agent", r.UserAgent()),
37		)
38	})
39}
40
41type loggingResponseWriter struct {
42	http.ResponseWriter
43	statusCode int
44}
45
46func (lrw *loggingResponseWriter) WriteHeader(code int) {
47	lrw.statusCode = code
48	lrw.ResponseWriter.WriteHeader(code)
49}
50
51func (lrw *loggingResponseWriter) Unwrap() http.ResponseWriter {
52	return lrw.ResponseWriter
53}