Log HTTP request and response body sizes

This commit is contained in:
Ingo Oppermann
2022-09-07 13:53:26 +02:00
parent 5cb0592854
commit 2d754b4212
3 changed files with 76 additions and 90 deletions

View File

@@ -1,65 +0,0 @@
// Package bodysize is an echo middleware that fixes the final number of body bytes sent on the wire
package bodysize
import (
"net/http"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
type Config struct {
Skipper middleware.Skipper
}
var DefaultConfig = Config{
Skipper: middleware.DefaultSkipper,
}
func New() echo.MiddlewareFunc {
return NewWithConfig(DefaultConfig)
}
// New return a new bodysize middleware handler
func NewWithConfig(config Config) echo.MiddlewareFunc {
if config.Skipper == nil {
config.Skipper = DefaultConfig.Skipper
}
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
if config.Skipper(c) {
return next(c)
}
res := c.Response()
writer := res.Writer
w := &fakeWriter{
ResponseWriter: res.Writer,
}
res.Writer = w
defer func() {
res.Writer = writer
res.Size = w.size
}()
return next(c)
}
}
}
type fakeWriter struct {
http.ResponseWriter
size int64
}
func (w *fakeWriter) Write(body []byte) (int, error) {
n, err := w.ResponseWriter.Write(body)
w.size += int64(n)
return n, err
}

View File

@@ -2,6 +2,7 @@
package log
import (
"io"
"net/http"
"time"
@@ -45,40 +46,92 @@ func NewWithConfig(config Config) echo.MiddlewareFunc {
start := time.Now()
req := c.Request()
var reader io.ReadCloser
r := &sizeReadCloser{}
if req.Body != nil {
reader = req.Body
r.ReadCloser = req.Body
req.Body = r
}
res := c.Response()
writer := res.Writer
w := &sizeWriter{
ResponseWriter: res.Writer,
}
res.Writer = w
path := req.URL.Path
raw := req.URL.RawQuery
if err := next(c); err != nil {
c.Error(err)
}
defer func() {
res.Writer = writer
req.Body = reader
latency := time.Since(start)
latency := time.Since(start)
if raw != "" {
path = path + "?" + raw
}
if raw != "" {
path = path + "?" + raw
}
logger := config.Logger.WithFields(log.Fields{
"client": c.RealIP(),
"method": req.Method,
"path": path,
"proto": req.Proto,
"status": res.Status,
"status_text": http.StatusText(res.Status),
"size_bytes": res.Size,
"latency_ms": latency.Milliseconds(),
"user_agent": req.Header.Get("User-Agent"),
})
logger := config.Logger.WithFields(log.Fields{
"client": c.RealIP(),
"method": req.Method,
"path": path,
"proto": req.Proto,
"status": res.Status,
"status_text": http.StatusText(res.Status),
"tx_size_bytes": w.size,
"rx_size_bytes": r.size,
"latency_ms": latency.Milliseconds(),
"user_agent": req.Header.Get("User-Agent"),
})
if res.Status >= 400 {
logger.Warn().Log("")
}
if res.Status >= 400 {
logger.Warn().Log("")
}
logger.Debug().Log("")
logger.Debug().Log("")
}()
return nil
return next(c)
}
}
}
type sizeWriter struct {
http.ResponseWriter
size int64
}
func (w *sizeWriter) Write(body []byte) (int, error) {
n, err := w.ResponseWriter.Write(body)
w.size += int64(n)
return n, err
}
type sizeReadCloser struct {
io.ReadCloser
size int64
}
func (r *sizeReadCloser) Read(p []byte) (int, error) {
n, err := r.ReadCloser.Read(p)
r.size += int64(n)
return n, err
}
func (r *sizeReadCloser) Close() error {
err := r.ReadCloser.Close()
return err
}

View File

@@ -51,7 +51,6 @@ import (
"github.com/datarhei/core/v16/session"
"github.com/datarhei/core/v16/srt"
mwbodysize "github.com/datarhei/core/v16/http/middleware/bodysize"
mwcache "github.com/datarhei/core/v16/http/middleware/cache"
mwcors "github.com/datarhei/core/v16/http/middleware/cors"
mwgzip "github.com/datarhei/core/v16/http/middleware/gzip"
@@ -341,7 +340,6 @@ func NewServer(config Config) (Server, error) {
return nil
},
}))
s.router.Use(mwbodysize.New())
s.router.Use(mwsession.NewHTTPWithConfig(mwsession.HTTPConfig{
Collector: config.Sessions.Collector("http"),
}))