为了账号安全,请及时绑定邮箱和手机立即绑定

go微服务中如何给每条日志添加trace id

go微服务中如何给每条日志添加trace id

Go
慕森王 2023-06-19 17:00:33
我想将跟踪 ID 添加到针对微服务的每个请求完成的日志记录中。我希望这与 springboot 应用程序类似,我们可以在 MDC 中设置跟踪 ID 并获取它并在日志记录时使用它。我做了一些研究,发现 go lang 中的 MDC 等价物是上下文。所以,我已经在我的上下文中设置了跟踪 ID。现在的问题是我必须使用跟踪 ID 登录的地方,我需要将上下文传递给该函数,这是非常丑陋的方式。我正在为这个问题寻找更好的解决方案。func HandlerFunction(f gin.HandlerFunc) gin.HandlerFunc{    return func(cxt *gin.Context) {        reqraceId := cxt.Request.Header.Get("trace-id")        requid , _ := uuid.NewRandom()        if reqTraceId == "" {            c.Request.Header.Set("trace-id", requid.String())        }        f(c)    }}
查看完整描述

3 回答

?
犯罪嫌疑人X

TA贡献2080条经验 获得超4个赞

context.Context其中有一节说:

在谷歌,我们要求 Go 程序员将 Context 参数作为第一个参数传递给传入和传出请求之间的调用路径上的每个函数。

TL;DR - 传递上下文很好,但最好的方法是什么?

有两种主要模式

  1. 询问上下文给你一个记录器

  2. 为记录器提供上下文

上下文可用于存储值:

context.WithValue(ctx, someKey, someValue)

这意味着我们可以这样做:

somepackage.Log(ctx).Info("hello world")
// or
sompackage.Info(ctx, "hello world")

这两个示例 API 的实现可以与上下文交互以检索所需的值,而无需担心任何日志调用站点的 MDC 中的额外信息。


查看完整回答
反对 回复 2023-06-19
?
慕妹3242003

TA贡献1824条经验 获得超6个赞

在我这边,我发现使用默认的日志包我们可以将前缀设置为log.SetPrefix(traceId),这样做,日志将打印跟踪 ID 作为实际和子函数/结构中的前缀。


import (

    "log"

    "github.com/google/uuid"

)


func (hdl *HTTPHandler) example() {

    var traceId string = uuid.NewString()

    log.SetPrefix(traceId + " - ")

    log.SetFlags(log.LstdFlags)

    // ...

    // ...

    log.Println("......")

}


查看完整回答
反对 回复 2023-06-19
?
DIEA

TA贡献1820条经验 获得超2个赞

这个问题也可以使用依赖注入容器来解决。

我们可以实现“请求范围”注入,因此,对于每个请求,我们将重新创建所有使用请求范围依赖项的依赖树(记录器、错误报告器、通过上下文传播将请求发送到另一个服务的客户端)。

但据我所知,使用依赖注入容器并不是最佳实践,也不是“惯用”方式。

此外,这种方法可能会有一些性能和内存问题,因为我们将为每个请求重新创建对象。


查看完整回答
反对 回复 2023-06-19
  • 3 回答
  • 0 关注
  • 309 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信