separated logger middleware
This commit is contained in:
@@ -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
|
||||||
|
}
|
||||||
@@ -4,7 +4,11 @@ import (
|
|||||||
"net/http"
|
"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 {
|
func Handler(f HandlerFunc) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/angelbeltran/templater"
|
"github.com/angelbeltran/templater"
|
||||||
|
|
||||||
@@ -21,6 +20,7 @@ import (
|
|||||||
"ruben/inventory2/internal/domains/raw_events"
|
"ruben/inventory2/internal/domains/raw_events"
|
||||||
"ruben/inventory2/internal/server/middleware"
|
"ruben/inventory2/internal/server/middleware"
|
||||||
"ruben/inventory2/internal/server/response"
|
"ruben/inventory2/internal/server/response"
|
||||||
|
"ruben/inventory2/internal/server/router"
|
||||||
"ruben/inventory2/internal/server/webhooks"
|
"ruben/inventory2/internal/server/webhooks"
|
||||||
etsy_webhooks "ruben/inventory2/internal/server/webhooks/etsy"
|
etsy_webhooks "ruben/inventory2/internal/server/webhooks/etsy"
|
||||||
)
|
)
|
||||||
@@ -46,54 +46,7 @@ func NewServer(
|
|||||||
etsy *etsy_platform.Platform,
|
etsy *etsy_platform.Platform,
|
||||||
auth *authentication.Authenticator,
|
auth *authentication.Authenticator,
|
||||||
) *Server {
|
) *Server {
|
||||||
reqIDCh := newRequestIDProvider(ctx)
|
mux := router.NewMux(middleware.LogRequests(ctx, logger.WithGroup("request")))
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
s := &Server{
|
s := &Server{
|
||||||
log: logger,
|
log: logger,
|
||||||
|
|||||||
Reference in New Issue
Block a user