自定义gin日志中间件截断日志。

3

我使用自定义日志中间件,间歇性地发现截断的json对象被写入loggly。我已确认代码中正在传出的记录确实被截断。

日志使用zerolog格式化,然后在stdout和loggly之间进行T处理。

我使用的loggly包相当老,但似乎只是实现了一个带有缓冲区的io.Writerhttps://github.com/segmentio/go-loggly.

我的担心是gin在将日志写入缓冲区之前终止了上下文,写入被截断了?但是在gin文档提供的示例中,我没有看到任何特别不同的地方。我删除了尽可能多的无关代码,但仍然存在此问题。

写入STDOUT的日志是完整的,但通过loggly包发送的日志被截断了。

package main

import (
    "io"
    "os"

    "github.com/gin-gonic/gin"
    "github.com/rs/zerolog"
    "github.com/segmentio/go-loggly"
)

var logglyClient *loggly.Client

func init() {
    logglyToken := "potato"
    logglyClient = loggly.New(logglyToken)
}

func NewLogger() zerolog.Logger {
    writers := []io.Writer{zerolog.ConsoleWriter{Out: os.Stdout}}
    writers = append(writers, logglyClient)
    multiWriter := zerolog.MultiLevelWriter(writers...)
    logger := zerolog.New(multiWriter).With().Timestamp().Logger()

    return logger
}

func GinMiddleware() gin.HandlerFunc {
    return func(gctx *gin.Context) {
        logger := NewLogger()
        logger.Info().Msg("API request")

        gctx.Next()
    }
}

func main() {
    router := gin.New()
    router.Use(GinMiddleware())
    logger := NewLogger()
    router.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    logger.Info().Msg("Server Listening!")
    router.Run(":8080")
}

使用以下软件包:

github.com/gin-gonic/gin v1.7.7
github.com/rs/zerolog v1.26.0
github.com/segmentio/go-loggly v0.5.0

2
请分享MWE - Chandan
1
我无法重现这个问题。当我调用localhost:8080/ping时,浏览器中显示{"message":"pong"}。每次调用时,终端中也会显示INF API request。你能帮我们重现一下吗?到底是哪里出了问题? - EmmanuelB
1
使用Uber Zap包进行日志记录比编写自定义日志中间件更好。 - Prateek Gupta
这一行让我最担心,但总的来说,代码并不是很好。 - Nikifor
1个回答

0
在程序退出之前刷新loggly客户端即可。

https://github.com/segmentio/go-loggly/blob/7a70408c3650c37ba8e58a934f686d0c44cb9b58/loggly.go#L216


func main() {
    defer logglyClient.Flush()

    router := gin.New()
    router.Use(GinMiddleware())
    logger := NewLogger()
    router.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    logger.Info().Msg("Server Listening!")
    router.Run(":8080")
}

除此之外,您还需要实现服务器的优雅关闭,以防止程序突然退出。

Gin文档中有一个专门的示例。

https://chenyitian.gitbooks.io/gin-web-framework/content/docs/38.html

func main() {
    router := gin.Default()
    router.GET("/", func(c *gin.Context) {
        time.Sleep(5 * time.Second)
        c.String(http.StatusOK, "Welcome Gin Server")
    })

    srv := &http.Server{
        Addr:    ":8080",
        Handler: router,
    }

    go func() {
        // service connections
        if err := srv.ListenAndServe(); err != nil {
            log.Printf("listen: %s\n", err)
        }
    }()

    // Wait for interrupt signal to gracefully shutdown the server with
    // a timeout of 5 seconds.
    quit := make(chan os.Signal)
    signal.Notify(quit, os.Interrupt)
    <-quit
    log.Println("Shutdown Server ...")

    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    if err := srv.Shutdown(ctx); err != nil {
        log.Fatal("Server Shutdown:", err)
    }
    log.Println("Server exiting")
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接