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{ httpServer := &http.Server{
Addr: net.JoinHostPort(config.Host, config.Port), Addr: net.JoinHostPort(config.Host, config.Port),
Handler: logger.Middleware(mux), Handler: logger.Middleware(mux, false),
} }
go func() { go func() {
log.Printf("listening on %s\n", httpServer.Addr) log.Printf("listening on %s\n", httpServer.Addr)

View file

@ -2,6 +2,7 @@ package logger
import ( import (
"bufio" "bufio"
"bytes"
"errors" "errors"
"net" "net"
"net/http" "net/http"
@ -9,11 +10,20 @@ import (
type bodyWriter struct { type bodyWriter struct {
http.ResponseWriter http.ResponseWriter
body *bytes.Buffer
maxSize int
bytes int
status 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{ return &bodyWriter{
body: body,
maxSize: 64000,
ResponseWriter: writer, ResponseWriter: writer,
status: http.StatusNotImplemented, status: http.StatusNotImplemented,
} }
@ -21,6 +31,15 @@ func newBodyWriter(writer http.ResponseWriter) *bodyWriter {
// implements http.ResponseWriter // implements http.ResponseWriter
func (w *bodyWriter) Write(b []byte) (int, error) { 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) return w.ResponseWriter.Write(b)
} }

View file

@ -8,7 +8,7 @@ import (
"time" "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) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" && r.URL.Path == "/healthz" { if r.Method == "GET" && r.URL.Path == "/healthz" {
next.ServeHTTP(w, r) next.ServeHTTP(w, r)
@ -29,7 +29,7 @@ func Middleware(next http.Handler) http.Handler {
path := r.URL.Path path := r.URL.Path
query := r.URL.RawQuery query := r.URL.RawQuery
bw := newBodyWriter(w) bw := newBodyWriter(w, recordBody)
next.ServeHTTP(bw, r) next.ServeHTTP(bw, r)
@ -45,8 +45,12 @@ func Middleware(next http.Handler) http.Handler {
responseAttributes := []slog.Attr{ responseAttributes := []slog.Attr{
slog.Time("time", end.UTC()), slog.Time("time", end.UTC()),
slog.Duration("latency", end.Sub(start)), slog.Duration("latency", end.Sub(start)),
slog.Int("length", bw.bytes),
slog.Int("status", bw.status), slog.Int("status", bw.status),
} }
if recordBody {
responseAttributes = append(responseAttributes, slog.String("body", bw.body.String()))
}
attributes := []slog.Attr{ attributes := []slog.Attr{
{ {
Key: "request", Key: "request",