electricity_bill_calc_service/logger/middleware.go

88 lines
1.7 KiB
Go

package logger
import (
"os"
"strconv"
"sync"
"time"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
)
// Config defines the config for middleware
type LogMiddlewareConfig struct {
// Next defines a function to skip this middleware when returned true.
//
// Optional. Default: nil
Next func(c *fiber.Ctx) bool
// Logger defines zap logger instance
Logger *zap.Logger
}
// New creates a new middleware handler
func NewLogMiddleware(config LogMiddlewareConfig) fiber.Handler {
var (
errPadding = 15
start, stop time.Time
once sync.Once
errHandler fiber.ErrorHandler
)
return func(c *fiber.Ctx) error {
if config.Next != nil && config.Next(c) {
return c.Next()
}
once.Do(func() {
errHandler = c.App().Config().ErrorHandler
stack := c.App().Stack()
for m := range stack {
for r := range stack[m] {
if len(stack[m][r].Path) > errPadding {
errPadding = len(stack[m][r].Path)
}
}
}
})
start = time.Now()
chainErr := c.Next()
if chainErr != nil {
if err := errHandler(c, chainErr); err != nil {
_ = c.SendStatus(fiber.StatusInternalServerError)
}
}
stop = time.Now()
fields := []zap.Field{
zap.Namespace("context"),
zap.String("pid", strconv.Itoa(os.Getpid())),
zap.String("time", stop.Sub(start).String()),
zap.Object("response", Resp(c.Response())),
zap.Object("request", Req(c)),
}
if u := c.Locals("userId"); u != nil {
fields = append(fields, zap.Uint("userId", u.(uint)))
}
formatErr := ""
if chainErr != nil {
formatErr = chainErr.Error()
fields = append(fields, zap.String("error", formatErr))
config.Logger.With(fields...).Error(formatErr)
return nil
}
config.Logger.With(fields...).Info("api.request")
return nil
}
}