From f80dd84784b8eee91c4f11a9916713a1de2b5ba0 Mon Sep 17 00:00:00 2001 From: "Gustavo L de Mello (Guz)" Date: Mon, 21 Oct 2024 14:24:28 -0300 Subject: [PATCH] feat(logger,middlewares): add move information for each request --- app/app.go | 28 ++++++++++---------- router/middleware/dev.go | 55 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 65 insertions(+), 18 deletions(-) diff --git a/app/app.go b/app/app.go index 5b5936a..a969268 100644 --- a/app/app.go +++ b/app/app.go @@ -11,7 +11,6 @@ import ( devPages "forge.capytal.company/capytalcode/project-comicverse/pages/dev" "forge.capytal.company/capytalcode/project-comicverse/router" "forge.capytal.company/capytalcode/project-comicverse/router/middleware" - "forge.capytal.company/capytalcode/project-comicverse/router/rerrors" ) type App struct { @@ -54,26 +53,25 @@ func NewApp(opts ...AppOpts) *App { } func (a *App) Run() { - router := router.NewRouter() - - router.HandleRoutes(pages.PAGES) - router.Handle("/assets/", a.assets) - - if a.dev { - router.HandleRoutes(devPages.PAGES) - router.AddMiddleware(middleware.DevMiddleware) - } - logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ Level: slog.LevelDebug, })) mlogger := middleware.NewLoggerMiddleware(logger) - router.AddMiddleware(mlogger.Wrap) - mErrors := rerrors.NewErrorMiddleware(pages.ErrorPage{}.Component, logger) - router.AddMiddleware(mErrors.Wrap) + r := router.NewRouter() - if err := http.ListenAndServe(fmt.Sprintf(":%v", a.port), router); err != nil { + r.Use(mlogger.Wrap) + if a.dev { + r.Use(middleware.DevMiddleware) + + r.Handle("/_dev", devPages.Routes()) + } + + r.Handle("/assets/", a.assets) + + r.Handle("/", pages.Routes(logger)) + + if err := http.ListenAndServe(fmt.Sprintf(":%v", a.port), r); err != nil { log.Fatal(err) } } diff --git a/router/middleware/dev.go b/router/middleware/dev.go index a27afe3..2f57ea8 100644 --- a/router/middleware/dev.go +++ b/router/middleware/dev.go @@ -2,7 +2,9 @@ package middleware import ( "log/slog" + "math/rand" "net/http" + "strconv" ) func DevMiddleware(next http.Handler) http.Handler { @@ -23,13 +25,60 @@ func NewLoggerMiddleware(l *slog.Logger) *LoggerMiddleware { func (l *LoggerMiddleware) Wrap(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - l.log.Debug("Handling request", slog.String("path", r.URL.Path)) + id := randHash(5) + + l.log.Info("NEW REQUEST", + slog.String("id", id), + slog.String("status", "xxx"), + slog.String("method", r.Method), + slog.String("path", r.URL.Path), + ) next.ServeHTTP(w, r) - l.log.Debug("Request finished", + s := w.Header().Get("Status") + if s == "" { + s = strconv.Itoa(http.StatusOK) + } + + sc, err := strconv.Atoi(s) + if err != nil { + l.log.Error("INVALID REQUEST STATUS", + slog.String("id", id), + slog.String("status", s), + slog.String("method", r.Method), + slog.String("path", r.URL.Path), + ) + return + } + if sc >= 400 { + l.log.Warn("ERR REQUEST", + slog.String("id", id), + slog.String("status", s), + slog.String("method", r.Method), + slog.String("path", r.URL.Path), + ) + return + } + + l.log.Info("END REQUEST", + slog.String("id", id), + slog.String("status", s), + slog.String("method", r.Method), slog.String("path", r.URL.Path), - slog.String("status", w.Header().Get("Status")), ) }) } + +const HASH_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + +// This is not the most performant function, as a TODO we could +// improve based on this Stackoberflow thread: +// https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-go +func randHash(n int) string { + b := make([]byte, n) + for i := range b { + b[i] = HASH_CHARS[rand.Int63()%int64(len(HASH_CHARS))] + } + return string(b) +}