go-nunu / nunu

A CLI tool for building Go applications.
https://go-nunu.github.io/nunu/
MIT License
1.89k stars 133 forks source link

请问如何设置某个接口不打印请求和响应日志? #75

Open Think-Me opened 5 days ago

Think-Me commented 5 days ago

因为我这里有个文件流中转的接口,打印响应日志会有一大堆的16进制文件内容,会让日志文件特别大。

codingcn commented 5 days ago

简单的修改下中间件,添加个白名单的参数,我先给一份参考代码,后续有空我再同步到nunu仓库,代码类似这样,:

第一步,修改internal/server/http.go

s.Use(
    middleware.CORSMiddleware(),
    middleware.RateLimiterMiddleware(100),
    middleware.AesMiddleware(logger, conf, []string{
        "POST:/v1/upload",
        "GET:/v1/wallet/scan/pay",
        `GET:/v1/cloud-disk/token/.*`,
        `GET:/v1/wechat/mp/auth`,
        `GET:/v1/wechat/pay/auth`,
        `POST:/v1/wechat/push`,
        `POST:/v1/wechat/pay/notify`,
        `GET:/v1/robots.txt`,
        `GET:/sitemap.*`,
        `POST:/v1/alipay/notify`,
    }),
    middleware.SignMiddleware(logger, conf, []string{
        "GET:/v1/wallet/scan/pay",
        "POST:/v1/upload",
        `GET:/v1/cloud-disk/token/.*`,
        `GET:/v1/wechat/mp/auth`,
        `GET:/v1/wechat/pay/auth`,
        `POST:/v1/wechat/push`,
        `POST:/v1/wechat/pay/notify`,
        `GET:/v1/robots.txt`,
        `GET:/sitemap.*`,
        `POST:/v1/alipay/notify`,
    }),
    middleware.RequestLogMiddleware(logger, []string{
        "POST:/v1/upload",
        `GET:/v1/robots.txt`,
        `GET:/sitemap.*`,
    }),
    middleware.ResponseLogMiddleware(logger, []string{
        "POST:/v1/upload",
        `GET:/v1/robots.txt`,
        `GET:/sitemap.*`,
    }),
)

然后再修改下日志中间件的代码

第二步,修改internal/middleware/log.go


func RequestLogMiddleware(logger *log.Logger, whiteList []string) gin.HandlerFunc {
    return func(ctx *gin.Context) {
        for _, pattern := range whiteList {
            parts := strings.SplitN(pattern, ":", 2)
            if len(parts) == 2 {
                if ctx.Request.Method != parts[0] {
                    continue
                }
                pattern = parts[1]
            }
            matched, err := regexp.MatchString(pattern, ctx.Request.URL.Path)
            if err != nil {
                logger.WithContext(ctx).Error("Failed to match pattern", zap.Error(err))
                continue
            }
            if matched {
                ctx.Next()
                return
            }
        }
        // The configuration is initialized once per request
        trace := md5.Md5(uuid.GenUUID())
        logger.WithValue(ctx, zap.String("trace", trace))
        logger.WithValue(ctx, zap.String("request_method", ctx.Request.Method))
        logger.WithValue(ctx, zap.Any("request_headers", ctx.Request.Header))
        logger.WithValue(ctx, zap.String("request_url", ctx.Request.URL.String()))
        if ctx.Request.Body != nil {
            bodyBytes, _ := ctx.GetRawData()
            ctx.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
            logger.WithValue(ctx, zap.String("request_params", string(bodyBytes)))
        }
        logger.WithContext(ctx).Info("Request")
        ctx.Next()
    }
}
func ResponseLogMiddleware(logger *log.Logger, whiteList []string) gin.HandlerFunc {
    return func(ctx *gin.Context) {
        for _, pattern := range whiteList {
            parts := strings.SplitN(pattern, ":", 2)
            if len(parts) == 2 {
                if ctx.Request.Method != parts[0] {
                    continue
                }
                pattern = parts[1]
            }
            matched, err := regexp.MatchString(pattern, ctx.Request.URL.Path)
            if err != nil {
                logger.WithContext(ctx).Error("Failed to match pattern", zap.Error(err))
                continue
            }
            if matched {
                ctx.Next()
                return
            }
        }
        blw := &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: ctx.Writer}
        ctx.Writer = blw
        startTime := time.Now()
        ctx.Next()
        duration := time.Since(startTime).String()
        ctx.Header("X-Response-Time", duration)
        logger.WithContext(ctx).Info("Response", zap.Any("response_body", blw.body.String()), zap.Any("time", duration))
    }
}

type bodyLogWriter struct {
    gin.ResponseWriter
    body *bytes.Buffer
}

func (w bodyLogWriter) Write(b []byte) (int, error) {
    w.body.Write(b)
    return w.ResponseWriter.Write(b)
}