Chi Middleware Request Logging
Log every request with chi middleware: request ids, durations, status codes, and route patterns instead of raw paths.
Code
package main
import (
"fmt"
"log/slog"
"net/http"
"os"
"time"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
func main() {
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelInfo,
}))
r := chi.NewRouter()
r.Use(middleware.RequestID)
r.Use(middleware.RealIP)
r.Use(requestLogger(logger))
r.Use(middleware.Recoverer)
r.Get("/orders/{orderID}", func(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "orderID")
logger.InfoContext(r.Context(), "order fetched",
slog.String("order_id", id),
)
w.Write([]byte("order " + id))
})
http.ListenAndServe(":8080", r)
}
func requestLogger(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) {
started := time.Now()
wrapped := middleware.NewWrapResponseWriter(w, r.ProtoMajor)
defer func() {
logger.LogAttrs(r.Context(), slog.LevelInfo, "request",
slog.String("request_id", middleware.GetReqID(r.Context())),
slog.String("method", r.Method),
slog.String("route", chi.RouteContext(r.Context()).RoutePattern()),
slog.Int("status", wrapped.Status()),
slog.Int("bytes", wrapped.BytesWritten()),
slog.Duration("duration", time.Since(started)),
)
}()
next.ServeHTTP(wrapped, r)
})
}
}Report a problem with this exampleOpens a pre-filled issue on GitHub.