refactor(app):基本完成基础服务框架的功能构建。

This commit is contained in:
徐涛
2022-09-28 16:01:16 +08:00
parent df9bf83bb8
commit 4b08952916
9 changed files with 334 additions and 152 deletions

View File

@@ -1,48 +1,87 @@
package logger
import (
"fmt"
"os"
"strconv"
"sync"
"time"
"github.com/gin-gonic/gin"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
)
func Logger() gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
path := c.Request.URL.Path
raw := c.Request.URL.RawQuery
// 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
// Process request
c.Next()
// Logger defines zap logger instance
Logger *zap.Logger
}
latency := time.Since(start)
// 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
)
clientIP := c.ClientIP()
method := c.Request.Method
statusCode := c.Writer.Status()
comment := c.Errors.ByType(gin.ErrorTypePrivate).String()
if raw != "" {
path = path + "?" + raw
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.Int("statusCode", statusCode),
zap.Duration("latency", latency),
zap.String("clientIP", clientIP),
zap.String("method", method),
zap.String("path", path),
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 comment != "" {
logger.Named("Gin").Error(
comment,
fields...,
)
} else {
logger.Named("Gin").Info(fmt.Sprintf("%s -> [%d] %s %s.", clientIP, statusCode, method, path), fields...)
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
}
}

119
logger/middleware_types.go Normal file
View File

@@ -0,0 +1,119 @@
package logger
import (
"bytes"
"encoding/json"
"strings"
"github.com/gofiber/fiber/v2"
"github.com/valyala/fasthttp"
"go.uber.org/zap/zapcore"
)
func getAllowedHeaders() map[string]bool {
return map[string]bool{
"User-Agent": true,
"X-Mobile": true,
}
}
type resp struct {
code int
_type string
}
func Resp(r *fasthttp.Response) *resp {
return &resp{
code: r.StatusCode(),
_type: bytes.NewBuffer(r.Header.ContentType()).String(),
}
}
func (r *resp) MarshalLogObject(enc zapcore.ObjectEncoder) error {
enc.AddString("type", r._type)
enc.AddInt("code", r.code)
return nil
}
type req struct {
body string
fullPath string
user string
ip string
method string
route string
headers *headerbag
}
func Req(c *fiber.Ctx) *req {
reqq := c.Request()
var body []byte
buffer := new(bytes.Buffer)
err := json.Compact(buffer, reqq.Body())
if err != nil {
body = reqq.Body()
} else {
body = buffer.Bytes()
}
headers := &headerbag{
vals: make(map[string]string),
}
allowedHeaders := getAllowedHeaders()
reqq.Header.VisitAll(func(key, val []byte) {
k := bytes.NewBuffer(key).String()
if _, exist := allowedHeaders[k]; exist {
headers.vals[strings.ToLower(k)] = bytes.NewBuffer(val).String()
}
})
var userEmail string
if u := c.Locals("userEmail"); u != nil {
userEmail = u.(string)
}
return &req{
body: bytes.NewBuffer(body).String(),
fullPath: bytes.NewBuffer(reqq.RequestURI()).String(),
headers: headers,
ip: c.IP(),
method: c.Method(),
route: c.Route().Path,
user: userEmail,
}
}
func (r *req) MarshalLogObject(enc zapcore.ObjectEncoder) error {
enc.AddString("fullPath", r.fullPath)
enc.AddString("ip", r.ip)
enc.AddString("method", r.method)
enc.AddString("route", r.route)
if r.body != "" {
enc.AddString("body", r.body)
}
if r.user != "" {
enc.AddString("user", r.user)
}
err := enc.AddObject("headers", r.headers)
if err != nil {
return err
}
return nil
}
type headerbag struct {
vals map[string]string
}
func (h *headerbag) MarshalLogObject(enc zapcore.ObjectEncoder) error {
for k, v := range h.vals {
enc.AddString(k, v)
}
return nil
}