feat(logger): implement optional body logging
This commit is contained in:
parent
7251421f55
commit
71702002cf
3 changed files with 28 additions and 5 deletions
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
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{
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
|
|
Loading…
Add table
Reference in a new issue