mirror of
https://github.com/datarhei/core.git
synced 2025-09-26 20:11:29 +08:00
Log HTTP request and response body sizes
This commit is contained in:
@@ -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
|
||||
}
|
@@ -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
|
||||
}
|
||||
|
@@ -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"),
|
||||
}))
|
||||
|
Reference in New Issue
Block a user