简体   繁体   English

如何在 go 微服务中为每个日志添加跟踪 ID

[英]How to add trace id to each logs in go micro service

I wanted to add trace id to logging done for each request to the micro service.I want this in similar as for springboot application we can set trace id in MDC and fetch it and use it while logging.我想将跟踪 id 添加到对微服务的每个请求的日志记录中。我希望这与 springboot 应用程序类似,我们可以在 MDC 中设置跟踪 id 并获取它并在记录时使用它。

I have done some research and I found that MDC equivalent in go lang is context.我做了一些研究,发现 go lang 中的 MDC 等效项是上下文。 So, I have set the trace id in my context.所以,我已经在我的上下文中设置了跟踪 ID。 Now the problem is where ever I have to log with trace id,I need to pass context to that function which is very ugly way.现在的问题是我必须使用跟踪 id 登录的地方,我需要将上下文传递给 function,这是非常丑陋的方式。 I am looking for a better solution for this problem.我正在为这个问题寻找更好的解决方案。

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)
    }
}

It might be worth reading up on context.Context particularly this article which has a section that says:可能值得阅读context.Context尤其是这篇文章,其中有一节说:

At Google, we require that Go programmers pass a Context parameter as the first argument to every function on the call path between incoming and outgoing requests.在 Google,我们要求 Go 程序员将 Context 参数作为第一个参数传递给传入和传出请求之间的调用路径上的每个 function。

TL;DR - it's fine to pass the context, but what's the best way? TL;DR - 传递上下文很好,但最好的方法是什么?

There's two main patterns有两种主要模式

  1. Ask the context to give you a logger询问上下文给你一个记录器
  2. Give the logger the context为记录器提供上下文

Context can be used to store values:上下文可用于存储值:

context.WithValue(ctx, someKey, someValue)

This means we can either do:这意味着我们可以这样做:

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

The implementation of these two sample APIs could interact with the context to retrieve the values required with out needing to worry about the extra information that would have been in MDC at any of the logging call sites.这两个示例 API 的实现可以与上下文交互以检索所需的值,而无需担心任何日志调用站点的 MDC 中可能存在的额外信息。

This issue can also be solved using a dependency injection container.这个问题也可以使用依赖注入容器来解决。

We can implement "request-scoped" injections, and as a result, for each request, we will recreate all dependency tree that uses request-scoped dependency(logger, error reporter, clients which send requests to another service with context propagation).我们可以实现“请求范围”注入,因此,对于每个请求,我们将重新创建所有使用请求范围依赖的依赖树(记录器、错误报告器、通过上下文传播向另一个服务发送请求的客户端)。

But as I understood using dependency injection containers is not a best practice in go and not an "idiomatic" way.但据我了解,在 go 中使用依赖注入容器不是最佳实践,也不是“惯用”方式。

Also, this approach can have some performance and memory issues since we will recreate objects for each request.此外,这种方法可能有一些性能和 memory 问题,因为我们将为每个请求重新创建对象。

From my side I found that using the default log package we could set a prefix as log.SetPrefix(traceId) , doing so, the log will print the trace id as the prefix in the actual and sub-functions/structs.从我的角度来看,我发现使用默认日志 package 我们可以将前缀设置为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("......")
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将 AWS SNS 消息传递到特定微服务的所有实例 - How to deliver AWS SNS message to all instances of particular micro service 如何更改我的 lambda 中的 Xray 跟踪 ID? - How can I change trace id in my lambda for xray? 轮换日志 - 如何在日志文件名中添加时间戳? - Rotation logs - How to add timestamp to log file name? 如何创建与请求日志的跟踪 ID 相关的 Google Cloud Logging 条目? - How to create Google Cloud Logging entries that are correlated with the request log's trace ID? 如何使用 Go 将文档 ID 作为字段值 Firestore 插入 - How to insert document id as a field value Firestore with Go Go 应用程序作为系统服务运行 - Go application run as systemd service 如何找到每个用户 ID 的第二个最小登录时间 - How to find the second minimum log in time per each user id 如何为 Firebase 添加通知服务扩展? - How to add Notification Service Extension for Firebase? 如何使用 JSON 服务帐户密钥在 GO 中获取 Kubernetes 客户端集? - How can I get a Kubernetes clientset in GO using a JSON service account key? 如何使用 Go 从 firebase 应用程序创建的服务帐户生成访问令牌 - How to generate an access token from a service account created from firebase app using Go
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM