diff options
author | Julien Dessaux | 2025-01-03 00:54:15 +0100 |
---|---|---|
committer | Julien Dessaux | 2025-01-03 00:54:15 +0100 |
commit | c18d03d4049e7fe2e032ba448e88a44671dfdbeb (patch) | |
tree | 09cfe305f3bb468b9a3a750c92c9b54e574a21ab /pkg/middlewares/logger/middleware.go | |
parent | feat(tfstated): bootstrap webui listening on a second port (diff) | |
download | tfstated-c18d03d4049e7fe2e032ba448e88a44671dfdbeb.tar.gz tfstated-c18d03d4049e7fe2e032ba448e88a44671dfdbeb.tar.bz2 tfstated-c18d03d4049e7fe2e032ba448e88a44671dfdbeb.zip |
chore(tfstated): refactor middlewares
Diffstat (limited to 'pkg/middlewares/logger/middleware.go')
-rw-r--r-- | pkg/middlewares/logger/middleware.go | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/pkg/middlewares/logger/middleware.go b/pkg/middlewares/logger/middleware.go new file mode 100644 index 0000000..54cca96 --- /dev/null +++ b/pkg/middlewares/logger/middleware.go @@ -0,0 +1,72 @@ +package logger + +import ( + "log/slog" + "net/http" + "runtime/debug" + "strconv" + "time" +) + +func Middleware(next http.Handler, recordBody bool) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method == "GET" && r.URL.Path == "/healthz" { + next.ServeHTTP(w, r) + return + } + + defer func() { + if err := recover(); err != nil { + w.WriteHeader(http.StatusInternalServerError) + slog.Error( + "panic", + "err", err, + "trace", string(debug.Stack()), + ) + } + }() + start := time.Now() + path := r.URL.Path + query := r.URL.RawQuery + + bw := newBodyWriter(w, recordBody) + + next.ServeHTTP(bw, r) + + end := time.Now() + requestAttributes := []slog.Attr{ + slog.Time("time", start.UTC()), + slog.String("method", r.Method), + slog.String("host", r.Host), + slog.String("path", path), + slog.String("query", query), + slog.String("ip", r.RemoteAddr), + } + responseAttributes := []slog.Attr{ + slog.Time("time", end.UTC()), + slog.Duration("latency", end.Sub(start)), + slog.Int("length", bw.bytes), + slog.Int("status", bw.status), + } + if recordBody { + responseAttributes = append(responseAttributes, slog.String("body", bw.body.String())) + } + attributes := []slog.Attr{ + { + Key: "request", + Value: slog.GroupValue(requestAttributes...), + }, + { + Key: "response", + Value: slog.GroupValue(responseAttributes...), + }, + } + level := slog.LevelInfo + if bw.status >= http.StatusInternalServerError { + level = slog.LevelError + } else if bw.status >= http.StatusBadRequest && bw.status < http.StatusInternalServerError { + level = slog.LevelWarn + } + slog.LogAttrs(r.Context(), level, strconv.Itoa(bw.status)+": "+http.StatusText(bw.status), attributes...) + }) +} |