首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >日志中的日志请求id

日志中的日志请求id
EN

Stack Overflow用户
提问于 2022-04-12 03:59:03
回答 1查看 1.4K关注 0票数 0

我正在开发一个现有的应用程序,它是用Go编写的,使用的是gin、中间件等框架。此应用程序使用https://pkg.go.dev/log进行日志记录。

我正在尝试为API调用跟踪向日志添加一个请求id。

main.go

代码语言:javascript
复制
        // Creates a router without any middleware by default
        r := gin.New()
        r.Use(middleware.RequestID())

middleware.go

代码语言:javascript
复制
func (m *Middleware) CheckApiToken(allowWithoutAccessKey bool, validateTonce ...bool) gin.HandlerFunc {
    return func(c *gin.Context) {

            // Validate
            .....
            .....
            logger.InitializeContext(c)
            c.Next()
        }
    }
}


//RequestID is a middleware that injects a 'RequestID' into the context and header of each request.
func (m *Middleware) RequestID() gin.HandlerFunc {
    return func(c *gin.Context) {
        xRequestID := uuid.NewV4().String()
        c.Request.Header.Set(logger.XRequestIDKey, xRequestID)
        fmt.Printf("[GIN-debug] %s [%s] - \"%s %s\"\n", time.Now().Format(time.RFC3339), xRequestID, c.Request.Method, c.Request.URL.Path)
        c.Next()
    }
}

logger.go

代码语言:javascript
复制
const (
    XRequestIDKey = "X-Request-ID"
)

var (
    infoLogger  *log.Logger
    errorLogger *log.Logger
    context     *gin.Context
)

func init() {

    infoLogger = log.New(os.Stdout, "", 0)
    errorLogger = log.New(os.Stderr, "", 0)
}

// InitializeContext initialize golbal gin context to logger
func InitializeContext(c *gin.Context) {
    context = c
}

//Check if the request id present in the context.
func getRequestID() interface{} {
    if context != nil {
        if context.Request != nil {
            requestID := context.Request.Header.Get(XRequestIDKey)
            if requestID != "" {
                return requestID
            }
        }
    }
    return ""
}

func Info(entry Input) {
    infoLogger.Println(getJSON(getRequestID(), msg))
}

这在多线程环境中不起作用。如何在多线程环境中修复此解决方案?

EN

回答 1

Stack Overflow用户

发布于 2022-04-12 04:16:24

不能将上下文保存在全局变量中。根据定义,上下文是该执行的本地内容,并且在任何给定的时刻,都会有多个上下文。

您可以将生成的ID存储在gin上下文中:

代码语言:javascript
复制
func (m *Middleware) RequestID() gin.HandlerFunc {
    return func(c *gin.Context) {
        xRequestID := uuid.NewV4().String()
        c.Set("requestId",xRequestID)
        fmt.Printf("[GIN-debug] %s [%s] - \"%s %s\"\n", time.Now().Format(time.RFC3339), xRequestID, c.Request.Method, c.Request.URL.Path)
        c.Next()
    }
}

然后,您可以使用存储在上下文中的ID和自定义日志格式化程序:

代码语言:javascript
复制
router.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {

        return fmt.Sprintf("%s ...",
                param.Keys["requestId"],
               ...
        )
    }))

或者,如果您需要使用不同的日志库,可以编写一个包装器:

代码语言:javascript
复制
func LogInfo(ctx *gin.Context,msg string) {
   id:=ctx.Get("requestId")
   // Log msg with ID
}

许多日志库提供了一些方法来获取已经设置了一些参数的记录器。例如,如果使用zerolog:

代码语言:javascript
复制
logger:=log.Info().With().Str("requestId",ctx.Get("requestId")).Logger()

logger.Info().Msg("This log msg will contain the request id")
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71836926

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档