separated logger middleware

This commit is contained in:
2026-01-11 17:05:20 -07:00
parent 9de51c3925
commit 85ccace24f
5 changed files with 124 additions and 84 deletions
+81
View File
@@ -0,0 +1,81 @@
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
}
+5 -1
View File
@@ -4,7 +4,11 @@ import (
"net/http"
)
type HandlerFunc = func(r *http.Request) (Response, error)
type (
HandlerFunc = func(r *http.Request) (Response, error)
Middleware = func(HandlerFunc) HandlerFunc
)
func Handler(f HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
-34
View File
@@ -1,34 +0,0 @@
package response
import "net/http"
type (
Mux struct {
Mux *http.ServeMux
middleware []Middleware
}
Middleware = func(HandlerFunc) HandlerFunc
)
func NewMux(ms ...Middleware) *Mux {
return &Mux{
Mux: http.NewServeMux(),
middleware: ms,
}
}
func (m *Mux) Handle(pattern string, fn HandlerFunc) {
for _, mw := range m.middleware {
prev := fn
fn = mw(func(r *http.Request) (Response, error) {
return prev(r)
})
}
m.Mux.Handle(pattern, Handler(fn))
}
func (m *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
m.Mux.ServeHTTP(w, r)
}
+36
View File
@@ -0,0 +1,36 @@
package router
import (
"net/http"
"ruben/inventory2/internal/server/response"
)
type (
Mux struct {
Mux *http.ServeMux
middleware []response.Middleware
}
)
func NewMux(ms ...response.Middleware) *Mux {
return &Mux{
Mux: http.NewServeMux(),
middleware: ms,
}
}
func (m *Mux) Handle(pattern string, fn response.HandlerFunc) {
for _, mw := range m.middleware {
prev := fn
fn = mw(func(r *http.Request) (response.Response, error) {
return prev(r)
})
}
m.Mux.Handle(pattern, response.Handler(fn))
}
func (m *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
m.Mux.ServeHTTP(w, r)
}
+2 -49
View File
@@ -10,7 +10,6 @@ import (
"path"
"strconv"
"strings"
"time"
"github.com/angelbeltran/templater"
@@ -21,6 +20,7 @@ import (
"ruben/inventory2/internal/domains/raw_events"
"ruben/inventory2/internal/server/middleware"
"ruben/inventory2/internal/server/response"
"ruben/inventory2/internal/server/router"
"ruben/inventory2/internal/server/webhooks"
etsy_webhooks "ruben/inventory2/internal/server/webhooks/etsy"
)
@@ -46,54 +46,7 @@ func NewServer(
etsy *etsy_platform.Platform,
auth *authentication.Authenticator,
) *Server {
reqIDCh := newRequestIDProvider(ctx)
reqLog := logger.WithGroup("request")
mux := response.NewMux(func(fn response.HandlerFunc) response.HandlerFunc {
return func(r *http.Request) (response.Response, error) {
start := time.Now()
args := []any{
"id", <-reqIDCh,
"url", r.URL,
}
reqLog.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:
reqLog.Debug("Response", args...)
case 2:
reqLog.Debug("Response", args...)
case 3:
reqLog.Debug("Response", args...)
case 4:
reqLog.Warn("Response", args...)
default:
reqLog.Error("Response", args...)
}
return res, err
}
})
mux := router.NewMux(middleware.LogRequests(ctx, logger.WithGroup("request")))
s := &Server{
log: logger,