saasitone/pkg/middleware/log.go
2024-07-09 17:57:25 -07:00

75 lines
1.9 KiB
Go

package middleware
import (
"fmt"
"strconv"
"time"
"github.com/labstack/echo/v4"
"git.grosinger.net/tgrosinger/saasitone/pkg/log"
)
// SetLogger initializes a logger for the current request and stores it in the context.
// It's recommended to have this executed after Echo's RequestID() middleware because it will add
// the request ID to the logger so that all log messages produced from this request have the
// request ID in it. You can modify this code to include any other fields that you want to always
// appear.
func SetLogger() echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(ctx echo.Context) error {
// Include the request ID in the logger
rID := ctx.Response().Header().Get(echo.HeaderXRequestID)
logger := log.Ctx(ctx).With("request_id", rID)
// TODO include other fields you may want in all logs for this request
log.Set(ctx, logger)
return next(ctx)
}
}
}
// LogRequest logs the current request
// Echo provides middleware similar to this, but we want to use our own logger
func LogRequest() echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(ctx echo.Context) (err error) {
req := ctx.Request()
res := ctx.Response()
// Track how long the request takes to complete
start := time.Now()
if err = next(ctx); err != nil {
ctx.Error(err)
}
stop := time.Now()
sub := log.Ctx(ctx).With(
"ip", ctx.RealIP(),
"host", req.Host,
"referer", req.Referer(),
"status", res.Status,
"bytes_in", func() string {
cl := req.Header.Get(echo.HeaderContentLength)
if cl == "" {
cl = "0"
}
return cl
}(),
"bytes_out", strconv.FormatInt(res.Size, 10),
"latency", stop.Sub(start).String(),
)
msg := fmt.Sprintf("%s %s", req.Method, req.URL.RequestURI())
if res.Status >= 500 {
sub.Error(msg)
} else {
sub.Info(msg)
}
return nil
}
}
}