package middleware import ( "context" "log/slog" "net/http" "time" "ruben/inventory2/internal/server/response" ) func LogRequests(ctx context.Context, logger *slog.Logger) response.Middleware { reqIDCh := newRequestIDProvider(ctx) return func(fn response.HandlerFunc) response.HandlerFunc { return func(r *http.Request) (response.Response, error) { start := time.Now() args := []any{ "id", <-reqIDCh, "url", r.URL, } logger.Debug("Request", args...) res, err := fn(r) end := time.Now() var status int if err != nil { status = response.GetStatusFromError(err) } else { var ok bool if status, ok = res.GetStatus(); !ok { status = http.StatusOK } } args = append(args, "status", status, "elapsed", time.Duration(end.UnixNano()-start.UnixNano()), ) switch status / 100 { case 1: logger.Debug("Response", args...) case 2: logger.Debug("Response", args...) case 3: logger.Debug("Response", args...) case 4: logger.Warn("Response", args...) default: logger.Error("Response", args...) } return res, err } } } func newRequestIDProvider(ctx context.Context) <-chan int { reqIDCh := make(chan int) go func() { defer close(reqIDCh) nextReqID := 1 for { select { case reqIDCh <- nextReqID: nextReqID += 1 case <-ctx.Done(): return } } }() return reqIDCh }