package middleware import ( "bytes" "fmt" "log/slog" "net/http" "os" "time" ) type LoggingResponseWriter struct { http.ResponseWriter statusCode int responseBody *bytes.Buffer } func (w *LoggingResponseWriter) WriteHeader(code int) { w.statusCode = code w.ResponseWriter.WriteHeader(code) } func (w *LoggingResponseWriter) Write(b []byte) (int, error) { w.responseBody.Write(b) return w.ResponseWriter.Write(b) } func LoggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() rw := &LoggingResponseWriter{ ResponseWriter: w, statusCode: http.StatusOK, responseBody: &bytes.Buffer{}, } jsonHandler := slog.NewJSONHandler(os.Stderr, nil) myslog := slog.New(jsonHandler) next.ServeHTTP(rw, r) if rw.statusCode >= 400 { myslog.Error("Request", "IP", r.RemoteAddr, "Method", r.Method, "Path", r.URL.Path, "Status", rw.statusCode, "Duration", fmt.Sprint(time.Since(start)), "Response", rw.responseBody.String()) } else { myslog.Info("Request", "IP", r.RemoteAddr, "Method", r.Method, "Path", r.URL.Path, "Status", rw.statusCode, "Duration", fmt.Sprint(time.Since(start))) } }) }