feat(logger): implement optional body logging

This commit is contained in:
Julien Dessaux 2024-10-13 16:10:22 +02:00
parent 7251421f55
commit 71702002cf
Signed by: adyxax
GPG key ID: F92E51B86E07177E
3 changed files with 28 additions and 5 deletions

View file

@ -51,7 +51,7 @@ func run(
httpServer := &http.Server{
Addr: net.JoinHostPort(config.Host, config.Port),
Handler: logger.Middleware(mux),
Handler: logger.Middleware(mux, false),
}
go func() {
log.Printf("listening on %s\n", httpServer.Addr)

View file

@ -2,6 +2,7 @@ package logger
import (
"bufio"
"bytes"
"errors"
"net"
"net/http"
@ -9,11 +10,20 @@ import (
type bodyWriter struct {
http.ResponseWriter
status int
body *bytes.Buffer
maxSize int
bytes int
status int
}
func newBodyWriter(writer http.ResponseWriter) *bodyWriter {
func newBodyWriter(writer http.ResponseWriter, recordBody bool) *bodyWriter {
var body *bytes.Buffer
if recordBody {
body = bytes.NewBufferString("")
}
return &bodyWriter{
body: body,
maxSize: 64000,
ResponseWriter: writer,
status: http.StatusNotImplemented,
}
@ -21,6 +31,15 @@ func newBodyWriter(writer http.ResponseWriter) *bodyWriter {
// implements http.ResponseWriter
func (w *bodyWriter) Write(b []byte) (int, error) {
if w.body != nil {
if w.body.Len()+len(b) > w.maxSize {
w.body.Write(b[:w.maxSize-w.body.Len()])
} else {
w.body.Write(b)
}
}
w.bytes += len(b)
return w.ResponseWriter.Write(b)
}

View file

@ -8,7 +8,7 @@ import (
"time"
)
func Middleware(next http.Handler) http.Handler {
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)
@ -29,7 +29,7 @@ func Middleware(next http.Handler) http.Handler {
path := r.URL.Path
query := r.URL.RawQuery
bw := newBodyWriter(w)
bw := newBodyWriter(w, recordBody)
next.ServeHTTP(bw, r)
@ -45,8 +45,12 @@ func Middleware(next http.Handler) http.Handler {
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",